English Русский 中文 Español Deutsch Português 한국어 Français Italiano Türkçe
preview
一からの取引エキスパートアドバイザーの開発(第13部):Times & Trade (II)

一からの取引エキスパートアドバイザーの開発(第13部):Times & Trade (II)

MetaTrader 5トレーディングシステム | 12 8月 2022, 16:23
325 0
Daniel Jose
Daniel Jose

はじめに

前回の「Times & Trade (I)」稿では 、市場で実行された取引を可能な限り迅速に解釈できる指標を作成するための前提条件である代替チャート編成システムについて説明しました。ただし、このシステムはまだ完成していません。特定の情報にアクセスする方法を示す機能がまだありません。そのようなアクセスは、何が起こっているのかをよりよく理解するのに役立ちます。このような情報はチャートに直接表示することはできません。実際、そのような表示は実装できますが、解釈は非常に紛らわしくなります。したがって、データを古典的な方法(つまりテキスト形式の値)で表現するのが最善です。エキスパートアドバイザー(EA)には、このタスクを実行できるシステムがないため、それを実装する必要があります。

一部の読者がまったく必要としないかもしれない情報を追加することによって前回の記事を複雑にしないために (システムはそのような詳細に深く掘り下げなくても使用できるため)、ここでシステムを拡張してより完全なものにすることにしましたが、前回の記事で提案されたシステムに含まれていないものもあります。ただし、この情報は、市場で実際に何が起こっているかを理解するために必要な場合があります。


計画

ここで、1つのことを理解することが重要です。細かいことですが、悪魔は詳細に宿る(細かいところに落とし穴)と言うことわざもあるので、次の画像をご覧ください。

この画像で何かおかしいことにお気づきでしょうか。あまり意味がないかもしれませんが、おかしいところがあるのでよくご覧ください。

まだ異常にお気付きでない場合は、下のハイライト表示された領域をご覧ください。


何が起こっているかおわかりでしょうか。この時点でBID値とASK値に変化がありましたが、ここで実行された取引は1つだけです。BIDまたはASKの値に変化があったとしても、取引が1回だけにはなりません。しかし、そのようなことは実際には、あなたが考えるよりも一般的です。問題は、以下に示す読み取りモードを使用すると、通常そのようなことが見られないことです。

この市場分析手法を使用すると、BID値とASK値の動きはわかりません。市場は常に機能しており、誰もが取引を成立させようとしているように思えますが、これは真実ではありません。実際、市場参加者は特定のポイントにポジションを置き、市場の動きを待ちます。ポジションがヒットすると、その動きを利用して利益を得ようとします。このため、BIDまたはASK値は取引なしで変動します。これはプラットフォームで見ることができる事実ですが、この情報はあまり重要ではないと信じているほとんどの人には無視されています。

以下の図は、Times & Tradeシステムがどのように見えるかを示しています。

よく見ると、チャート上に4つのローソク足構成があることがわかります。5つあるはずですが、直接注文は実際には相場を動かさないため、システムから除外されているため、実際には4つの構成があります。次がフォーメーションです。

髭がローソク足の実体に触れないことがあります。なぜこうなったのでしょうか。髭は、BIDとASKの差であるスプレッドの値によって形成されますが、このスプレッド内で操作がおこなわれた場合、ローソク足はどのように見えるでしょうか。これは、次に示す5番目のタイプになります。

フォーメーションタイプによると、これは同事です。これが直接注文がシステムに表示されない理由ですが、実体が時々髭に触れない理由は説明できません。このような挙動は、価格の動きが速すぎる原因となる何かが発生した場合、つまり実体と髭の間に距離がある状況に関連しています。これはシステムの故障だと思うかもしれません。価格がこれを行うのは意味がないからです。しかし、これはまさに逆指値注文がトリガーされたときに発生するため、ここでは理にかなっています。これを確認するには、次の画像をご覧ください。

注文があるのにBIDもASKも触れないケースが相次いでいます。これらすべてのポイントは、トリガーされた逆指値注文を表します。これが発生すると、価格は通常ジャンプし、チャートで確認できます。同じ事実は、チャートモードを使用して動きを評価している場合にのみ、Times & Tradeで見ることができます。これがないと、ストップのトリガーが見えず、動きが強くなっていると思うかもしれませんが、実際にはすぐに戻ることができてストップにぶつかります.

これがわかったので、髭に触れていない大きな一連のローソク足がトリガーされた逆指値注文を表していることがわかります。実際、すべてが非常に迅速に発生するため、この動きが発生したときに正確にキャプチャすることは不可能です。ただし、BID値とASK値の解釈を使用して、これが発生した理由を見つけることができます。これは読者と読者の市場経験次第です。詳細には触れませんが、本当にテープリーディングを指標として使用したい場合は、これに注目する必要があります。

詳細は次のとおりです。この情報がローソク足を使用してのみ表示され、ローソク足自体で何らかの情報を学習するのに十分である場合、なぜより多くのデータが必要なのでしょうか。

詳細は、市場が遅くなり、現時点で出てくる情報を待っている時があるということですが、ローソク足でTimes & Tradeを見ただけではこれを知ることはできません.それ以上のものが必要です。この情報はシステム自体に存在しますが、そのまま解釈するのは困難です。分析しやすいようにデータをモデル化する必要があります。

このモデリングが、この記事を書く理由です。このモデリングが完了すると、Times & Tradeは次のように変化します。

言い換えれば、何が起こっているのかを完全に把握できます。さらに、すべてが高速になります。これは、テープリーディングを取引の方法として使用したい人にとって重要です。


実装

システムを実装するには、いくつかの新しい変数を C_TimesAndTradeクラスに追加する必要があります。それらは以下のコードに示されています。

#include <NanoEA-SIMD\Auxiliar\C_FnSubWin.mqh>
#include <NanoEA-SIMD\Auxiliar\C_Canvas.mqh>
//+------------------------------------------------------------------+
class C_TimesAndTrade : private C_FnSubWin
{
//+------------------------------------------------------------------+
#define def_SizeBuff 
2048 
#define macro_Limits(A) (A & 0xFF)
#define def_MaxInfos 257
//+------------------------------------------------------------------+
        private :
                string          m_szCustomSymbol,
                                m_szObjName;
                char            m_ConnectionStatus;
                datetime        m_LastTime;
                ulong           m_MemTickTime;
                int             m_CountStrings;
                struct st0
                {
                        string  szTime;
                        int     flag;
                }m_InfoTrades[def_MaxInfos];
                struct st1
                {
                        C_Canvas Canvas;
                        int      WidthRegion,
                                 PosXRegion,
                                 MaxY;
                        string   szNameCanvas;
                }m_InfoCanvas;


ハイライト表示は、ソースコードに追加された部分を示します。ご覧のとおり、C_Canvasクラスを使用する必要がありますが、必要な要素がすべて含まれているわけではありません。実際、この C_Canvasクラスに4つのサブルーチンを追加する必要があります。これらのサブルーチンを以下のコードに示します。

// ... C_Canvas class code

inline void FontSet(const string name, const int size, const uint flags = 0, const uint angle = 0)
{
        if(!TextSetFont(name, size, flags, angle)) return;
        TextGetSize("M", m_TextInfos.width, m_TextInfos.height);
}
//+------------------------------------------------------------------+
inline void TextOutFast(int x, int y, string text, const uint clr, uint alignment = 0)
{
        TextOut(text, x, y, alignment, m_Pixel, m_width, m_height, clr, COLOR_FORMAT_ARGB_NORMALIZE);
}
//+------------------------------------------------------------------+
inline int TextWidth(void) const { return m_TextInfos.width; }
//+------------------------------------------------------------------+
inline int TextHeight(void) const { return m_TextInfos.height; }
//+------------------------------------------------------------------+

// ... The rest of the code ...

これらの行はテキストを作成します。非常にシンプルなもので、極端にエレガントなものはありません。

このクラスで言及する価値のある次の関数はC_TimesAndTradeです。

void PrintTimeTrade(void)
{
        int ui1;
        
        m_InfoCanvas.Canvas.Erase(clrBlack, 220);
        for (int c0 = 0, c1 = m_CountStrings - 1, y = 2; (c0 <= 255) && (y < m_InfoCanvas.MaxY); c0++, c1--, y += m_InfoCanvas.Canvas.TextHeight())
        if (m_InfoTrades[macro_Limits(c1)].szTime == NULL) break; else
        {
                ui1 = m_InfoTrades[macro_Limits(c1)].flag;
                m_InfoCanvas.Canvas.TextOutFast(2, y, m_InfoTrades[macro_Limits(c1)].szTime, macroColorRGBA((ui1 == 0 ? clrLightSkyBlue : (ui1 > 0 ? clrForestGreen : clrFireBrick)), 220));
        }
        m_InfoCanvas.Canvas.Update();
}

この関数では、このために予約された特別な領域に値を表示します。さらに、初期化手順にも小さな変更が加えられました。これは、以下のハイライト表示された部分で確認できます。

void Init(const int iScale = 2)
{
        if (!ExistSubWin())
        {
                m_InfoCanvas.Canvas.FontSet("Lucida Console", 13);
                m_InfoCanvas.WidthRegion = (18 * m_InfoCanvas.Canvas.TextWidth()) + 4;
                CreateCustomSymbol();
                CreateChart();
                m_InfoCanvas.Canvas.Create(m_InfoCanvas.szNameCanvas, m_InfoCanvas.PosXRegion, 0, m_InfoCanvas.WidthRegion, TerminalInfoInteger(TERMINAL_SCREEN_HEIGHT), GetIdSubWinEA());
                Resize();
                m_ConnectionStatus = 0;
        }
        ObjectSetInteger(Terminal.Get_ID(), m_szObjName, OBJPROP_CHART_SCALE, (iScale > 5 ? 5 : (iScale < 0 ? 0 : iScale)));
}

Times & Tradeの代替ルーチンにも追加の変更が必要でした。変更は次のとおりです。

void Resize(void)
{
        static int MaxX = 0;
        int x = (int) ChartGetInteger(Terminal.Get_ID(), CHART_WIDTH_IN_PIXELS, GetIdSubWinEA());
        
        m_InfoCanvas.MaxY = (int) ChartGetInteger(Terminal.Get_ID(), CHART_HEIGHT_IN_PIXELS, GetIdSubWinEA());
        ObjectSetInteger(Terminal.Get_ID(), m_szObjName, OBJPROP_YSIZE, m_InfoCanvas.MaxY);
        if (MaxX != x)
        {
                MaxX = x;
                x -= m_InfoCanvas.WidthRegion;
                ObjectSetInteger(Terminal.Get_ID(), m_szObjName, OBJPROP_XSIZE, x);
                ObjectSetInteger(Terminal.Get_ID(), m_InfoCanvas.szNameCanvas, OBJPROP_XDISTANCE, x);
        }
        PrintTimeTrade();
}

システムの準備はほぼ整っていますが、システムの心臓部にあるサブルーチンがまだ必要です。次のように変更されました。

inline void Update(void)
{
        MqlTick Tick[];
        MqlRates Rates[def_SizeBuff];
        int i0, p1, p2 = 0;
        int iflag;
        long lg1;
        static int nSwap = 0;
        static long lTime = 0;

        if (m_ConnectionStatus < 3) return;
        if ((i0 = CopyTicks(Terminal.GetFullSymbol(), Tick, COPY_TICKS_ALL, m_MemTickTime, def_SizeBuff)) > 0)
        {
                for (p1 = 0, p2 = 0; (p1 < i0) && (Tick[p1].time_msc == m_MemTickTime); p1++);
                for (int c0 = p1, c1 = 0; c0 < i0; c0++)
                {
                        lg1 = Tick[c0].time_msc - lTime;
                        nSwap++;
                        if (Tick[c0].volume == 0) continue;
                        iflag = 0;
                        iflag += ((Tick[c0].flags & TICK_FLAG_BUY) == TICK_FLAG_BUY ? 1 : 0);
                        iflag -= ((Tick[c0].flags & TICK_FLAG_SELL) == TICK_FLAG_SELL ? 1 : 0);
                        if (iflag == 0) continue;
                        Rates[c1].high = Tick[c0].ask;
                        Rates[c1].low = Tick[c0].bid;
                        Rates[c1].open = Tick[c0].last;
                        Rates[c1].close = Tick[c0].last + ((Tick[c0].volume > 200 ? 200 : Tick[c0].volume) * (Terminal.GetTypeSymbol() == C_Terminal::WDO ? 0.02 : 1.0) * iflag);
                        Rates[c1].time = m_LastTime;
                        m_InfoTrades[macro_Limits(m_CountStrings)].szTime = StringFormat("%02.d.%03d ~ %02.d <>%04.d", ((lg1 - (lg1 % 1000)) / 1000) % 60 , lg1 % 1000, nSwap, Tick[c0].volume);
                        m_InfoTrades[macro_Limits(m_CountStrings)].flag = iflag;
                        m_CountStrings++;
                        nSwap = 0;
			lTime = Tick[c0].time_msc;
                        p2++;
                        c1++;
                        m_LastTime += 60;
                }
                CustomRatesUpdate(m_szCustomSymbol, Rates, p2);
                m_MemTickTime = Tick[i0 - 1].time_msc;
        }
        PrintTimeTrade();
}

ハイライト表示された行は、必要なデータをモデル化するためにサブルーチンに追加されたコードを表しています。次のコード

lg1 = Tick[c0].time_msc - lTime;
nSwap++;


は、ミリ秒単位で取引間に経過した時間と、価格の変化を引き起こさなかった取引の数をチェックします。これらの数値が大きい場合、回転率が低下していることがわかります。この機能を使用すると、他よりも早くこれに気付くことができます。

次の部分

m_InfoTrades[macro_Limits(m_CountStrings)].szTime = StringFormat("%02.d.%03d ~ %02.d <>%04.d", ((lg1 - (lg1 % 1000)) / 1000) % 60 , lg1 % 1000, nSwap, Tick[c0].volume);
m_InfoTrades[macro_Limits(m_CountStrings)].flag = iflag;
m_CountStrings++;
nSwap = 0;                                      
lTime = Tick[c0].time_msc;

は、提示される値をモデル化します。使用が制限されているため、m_CountStrings カウンタはテストしないことに注意してください。新しい情報が利用可能になったらその値を増やすだけです。これは、たまに使える裏技です。処理の点で効率的であるため、私自身も可能な限り使用しています。取引システムはリアルタイムで使用するように設計されているため、これは重要です。可能な限り常にシステムを最適化するように努める必要があります。たとえ少しであっても、最終的には、大きな違いが生まれます。

すべてが実装された後、EAをコンパイルして、次のようなものを取得します。


上記のTimes & Tradeチャートの動きを見ると、Times & Trade自体に微細構造が現れ始めていることがわかりますが、これらの微細構造を調べても、それらが存在するという事実を利用することはできませんでした.ただし、私はそれほど経験豊富なトレーダーではないので、もっと経験のある方ならできるかもしれません。

この指標は非常に強力で有益なので、その値と執筆時点でのアセットによって表示される実際のデータとの小さな比較を示すビデオを作成することにしました。多くの情報をフィルタリングすることで、データをはるかに高速に読み取って何が起こっているのかをよりよく理解できることを実証したいと思います。この素晴らしい強力な指標を楽しんで活用していただければ幸いです。




結論

ここで提案するシステムは、単にMetaTrader 5プラットフォーム自体で利用可能なチャートシステムを変更したものです。変更されたのはデータのモデリング方法です。プラットフォームで利用可能な最短の時間枠である1分で微細構造を形成することによって成立した取引が価格の方向にどのように影響するかを見るのは興味深いことです。多くの人は、あたかもそれが高度な市場知識を持っているかのように、分刻みの時間枠で取引をおこなっていると言うのが好きです。しかし、よく見て取引プロセスを理解すると、多くのことが1分以内に発生することが明らかになります。これは短い時間のように見えますが、これにより、多くの潜在的に収益性の高い取引を逃す可能性があります。この Times & Trade システムでは、1分以内に何が起こるかを見ていないことに注意してください。画面に表示される値はミリ秒単位で表示されます。


MetaQuotes Ltdによりポルトガル語から翻訳されました。
元の記事: https://www.mql5.com/pt/articles/10412

添付されたファイル |
EA_-_Times_m_Trade.zip (5983.76 KB)
一からの取引エキスパートアドバイザーの開発(第14部):価格別出来高の追加((II) 一からの取引エキスパートアドバイザーの開発(第14部):価格別出来高の追加((II)
今日は、EAにいくつかのリソースを追加します。この興味深い記事では、情報を提示するためのいくつかの新しいアイデアと方法を提供します。同時に、プロジェクトの小さな欠陥を修正するのにも役立ちます。
一からの取引エキスパートアドバイザーの開発(第12部):Times and Trade (I) 一からの取引エキスパートアドバイザーの開発(第12部):Times and Trade (I)
今日は、注文の流れを読むために、高速な解釈を持つTimes & Tradeを作成します。これは、システムを構築していくうえで最初の部分です。次回は、足りない情報を補って、システムを完成させる予定です。この新しい機能を実装するために、エキスパートアドバイザー(EA)のコードにいくつかの新しいものを追加する必要があります。
パラボリックSARによる取引システムの設計方法を学ぶ パラボリックSARによる取引システムの設計方法を学ぶ
最も人気のある指標を使用して取引システムを設計する方法についての連載を続けます。この記事では、パラボリックSAR指標について詳しく説明し、いくつかの簡単な戦略を使用してMetaTrader 5で使用する取引システムを設計する方法を学びます。
ATRによる取引システムの設計方法を学ぶ ATRによる取引システムの設計方法を学ぶ
簡単な取引システムの設計方法を学ぶ連載の続編として、取引に使用できる新しいテクニカルツールを学びます。今回は、もう1つの人気あるテクニカル指標であるATR(Average True Range、アベレージトゥルーレンジ)です。