一からの取引エキスパートアドバイザーの開発(第13部):Times & Trade (II)
はじめに
前回の「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自体に微細構造が現れ始めていることがわかりますが、これらの微細構造を調べても、それらが存在するという事実を利用することはできませんでした.ただし、私はそれほど経験豊富なトレーダーではないので、もっと経験のある方ならできるかもしれません。
この指標は非常に強力で有益なので、その値と執筆時点でのアセットによって表示される実際のデータとの小さな比較を示すビデオを作成することにしました。多くの情報をフィルタリングすることで、データをはるかに高速に読み取って何が起こっているのかをよりよく理解できることを実証したいと思います。この素晴らしい強力な指標を楽しんで活用していただければ幸いです。
結論
MetaQuotes Ltdによりポルトガル語から翻訳されました。
元の記事: https://www.mql5.com/pt/articles/10412
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索