チャート上のインタラクティブなコントロールを備えたインジケーター
はじめに
私は2008年から取引をしています。その過程でかなりの量の知識を蓄積したので、今では、この知識を製品開発に活かしています。何年にもわたって数十の異なる取引戦略を試し、数百の異なるインジケーターをテストしてきた結果、この記事で共有したいいくつかの結論に達しました。以前と同様に、MetaTrader取引プラットフォームの品質は疑う余地がありませんが、現代の状況では、ユーザーは提供される製品に対してより厳しい要求をするようになっています。そこで、どのインジケーターにも当てはまりやすい原理を作れたらいいと思いました。その原則は、ユーザーとプログラムの間のより多くの相互作用を目指しています。
インジケーターについて
MetaTraderプラットフォームは、さまざまなタイプの取引プログラムを備えています。エキスパートアドバイザー(EA)、スクリプト、インジケーターです。インジケーターについてお話しします。
インジケーターにはさまざまな種類があります。支持抵抗線、ローソク足フラクタルまたはパターン、証券取引所での取引操作に関するボリュームまたはその他のデータ、オシレーターまたはヒストグラムなどです。特定の価格変動パターンを示すためにはそれらすべてが必要であり、それが取引シグナルを形成します。パターンが頻繁に発生するほど、シグナルが強くなります。
パターンとは、特定のインジケーターの読み取り値で発生する反復したまたは非常に類似した価格変動です。たとえば、高速移動平均線が低速移動平均線を上に横切り、価格が下向きに横切る場合、価格はこの線から跳ね返って上昇し続ける可能性が高くなります。このようなパターンは、任意のインジケーターを使用しているときに見つけることができます。
各インジケーターは、その目的に関係なく、一定期間のパターンを示します。これは、履歴データの一部の領域における過去の価格変動に基づいてシグナルが形成されることを意味します。10 H1バーまたは1000 D1バーにすることができます。パターンを探している期間は、インジケーターの「期間」と呼ばれます。
すべてのインジケーターは過去のデータに基づいて計算されるため、どのインジケーターにも計算期間があります。期間値を100に設定し、インジケーターをH1チャートに配置すると、最後の100 H1ローソク足のインジケーター計算結果が得られます。インジケーター期間は、私たちが変更するまで変更されません。価格変動の性質が変化した場合、たとえば、動きがより不安定になった場合、現在の市場状況に対応するためにインジケーター期間を延長する必要があります。
これをおこなうには、インジケーター設定にアクセスして、新しい期間値を選択します。パラメーターは段階的に変更する必要があります。ステップは直感的に選択するのですが、必要なシグナルを見逃さないように大きすぎず、時間をかけすぎないように小さすぎず設定する必要があります。これを1日に頻繁におこなえば、かなりの時間を費やす場合があります。実際、インジケーターの使用は、望ましい結果、精度、トレーダーが費やす気がある時間の間の一種の妥協です。
別のオプションは、異なるインジケーター設定を持つ必要なすべてのチャートを一度に開くことです。この場合、作業スペース全体が、期間設定だけが互いに異なる同じタイプのインジケーターを含むウィンドウで雑然となります。この解決策は、ワークスペースの配置に関しても完璧ではありません。残念ながら、どちらのオプションもまったく便利ではありません。
問題の核心
長い間取引で使用してきた取引戦略を使用して、問題を強調したいと思います。多くのトレーダーが毎日同じ問題に直面していると思います。それに気づかず当たり前のように思っている人と、私と同じように不快感を感じる人がいます。戦略は、移動平均線の兆候に基づいています.。トレンドの動きでうまく機能します。その本質は、トレンドが始まった場合、おそらくそれが続くという事実にあり、取引シグナルは、修正中に価格が高速ラインに戻ることです。
高速ラインの期間を計算するには、前回の修正中に高速移動平均と低速移動平均の特定の位置を見つける必要があります。
必要な期間を見つけるには、多くの繰り返し操作を実行する必要があります。この戦略の特徴は、ライン期間が常に2倍で異なることです。たとえば、高速ラインの期間が20の場合、低速ラインの期間は40に等しくなります。この場合、修正中に高速ラインが低速ラインを横切らない、ライン期間の最小値を見つける必要があります。画像ではそれぞれ25と50の期間ラインを示しています。ご覧のとおり、前回の修正では線が交差していないため、さらに期間を短縮できます。高速ラインの設定を開き、期間を変更します。次に、低速ラインの設定を開き、期間も変更します。 ラインができるだけ近くに収束するまで、この操作を数回おこなう必要があります。
ラインはまだ交差していませんが、最初にラインが交差する極端な位置を見つけてから、それらの期間を1ステップ増やす必要があります。そのため、期間の設定をそれぞれ7と14に変更します。
これで交差ができました。これは極端な位置が見つかったことを意味し、期間を1ステップ増やす必要があります。各ラインの設定を再度開き、期間の値を変更します。
その結果、必要なラインパラメーターの組み合わせが見つかり、シグナルが正常に生成されましたが、検索の準備には一定の時間がかかり、単調で退屈な行動を余儀なくされました。これは単一の通貨ペアの1つの時間枠にすぎないことを忘れないでください。異なる時間枠で複数の通貨ペアをフォローするには、そのようなアクションを頻繁に実行する必要があります。私の経験によると、分単位の時間枠を使用すると、作業時間の少なくとも半分がこのプロセスにとられます。この戦略はおそらく非常に人気があり、多くのトレーダーは、日常の取引で似たものを使用していると思います。
この戦略の欠点は明らかです。インジケーター設定によるそのような絶え間ない操作には多くの時間がかかるという事実に加えて、それらは主要なアクティビティである取引からも気をそらします。新しいラインパラメーターを選択している間、別の通貨ペアまたは別の時間枠で既に形成されているシグナルが単に見過ごされる可能性があります。さらに、利益を最大にしてまたは損失を最小にして、時間内に取引を閉じることができない場合があります。これに加えて、そのような仕事を数時間続ければ、誰もが疲れ始めます。単調な行動によってトレーダーの気が緩み、エラーのリスクが高まります。かかった時間は言うまでもありません。コンピューターモニターで数年間作業した後で、自分の時間の大切さに気づき、そのような一見些細なことの重要性を理解し始めるようになります。
インターフェイスの原理
インターフェイスの背後にあるアイデアは、設定に入ることなくチャートから直接マウスホイールでインジケーター期間をスクロールすることです。ボタンを使用してスクロールモードを有効にします。
添付ファイルのボタンCCIインジケーターのソースコードをダウンロードして試すか、追加機能を備えた最新の無料バージョンをダウンロードし、リンクをたどってその設定の詳細な説明を参照してください。
問題は明確です。明らかに、どうにかして期間の設定を加速する必要があります。これをおこなう唯一の方法は、プロセスを自動化することです。独自に期間値を選択するアルゴリズムを作成することもできますが、アルゴリズムにはまだ独自の計算期間が必要です。つまり、アルゴリズムが移動平均期間を選択するために使用するローソク足の数を手動で設定する必要があるということです。これは一種の「メタ」期間です。目的の期間の選択にかかる時間の問題は解決されますが、このソリューションには複雑さによる欠点があります。このアプローチは、無料の動的二重移動平均インジケーターで実装されています。今後は、より管理しやすく、ユーザーが入力した設定の変更に対応できるように改善する予定です。
もう1つの方法は、私の意見では、よりシンプルであると同時によりインタラクティブです。より便利な形ではありますが、トレーダーによる期間の変更に関係します。結局のところ、アルゴリズムがどれほどスマートであっても、必要なインジケーター設定をよりよく知っているのはトレーダーです。私たちの仕事は彼らを助け、プロセスを促進することです.期間を変更するには、マウスホイールでスクロールします。チャートの右側にあるボタンをオンにすると、スクロールモード自体が有効になります。
この画像は、インジケーターの期間を1回の動作で簡単に変更できることを示しています。必要なインジケーターのボタンをアクティブにして、マウスホイールを目的の方向にスクロールするだけです。必要な期間変更ステップを設定することもできます。必要なボタンをアクティブにするだけで、複数のインジケーターの期間を一度に変更することもできます。これらの機能は、上記の戦略に最適です。たとえば、高速ラインを1に、低速ラインを2に変更するステップを設定し、両方のラインをスクロール可能にし、比率を1/2に保ちながら同時に期間を簡単に変更できます。
利点
- トレーダーは、時間と労力を大幅に削減しながらも、通常どおりインジケーター期間を調整できる
- インターフェイスが直感的で使いやすい(このようなインジケーターを長期間使用した後は、標準インターフェイスに戻りたくないでしょう)
- 複数の同じタイプのインジケーターを1つに置き換え、単一のウィンドウを使用でき、作業画面がすっきりする
- インジケーターの設定ではなくプロセス自体への集中度が高まるため、取引の質が向上する
- 急速に変化する市場でのシグナルの検索が加速され、トレーダーの生産性の向上に役立つ
欠点
これらすべての利点がある一方で、このようなインターフェイスには欠点があります。
- MQL4言語の技術的な制約により、MetaTrader 4 で再現することが困難
- 大量のデータ(20,000バー以上)で計算を実行すると、インジケーターが著しく遅くなる
ただし、履歴分析はそれほど頻繁に必要とされるわけではなく、日常的に使用する計算のデータ量を制限できます。 これらの欠点は重大ではなく、MetaTrader 5でのそのようなインジケーターの日常的な使用を妨げるものではありません。
移動平均に基づく期間スクロールを持つインジケーターの作成
上記に基づいて、ユーザーを日常的なアクションから救う最も便利なインターフェイスを備えたインジケーターを作成することが有用であると判断しました。また、目標は、ほとんどのインジケーターに対して最も単純な原則を作成することでした。これにより、同様のインターフェイスを他のインジケーターで簡単に再現できます。
例として、最も人気のあるインジケーターである移動平均を取り上げることにしました。アイデアの複雑さは、期間を動的に変更したい場合、数十、さらには数百のインジケーターを同時に使用する必要があるという事実にあります。システムは1つのウィンドウで使用されるインジケーターを短い名前とパラメーターのセットで区別するため、パラメーターのセットは、各変更ステップで「period」パラメーターが常に異なり、各期間に対して新しいインジケーターハンドルが作成されます。これによって、作業が大幅に遅くなる可能性があります。解決策を探しているときに、フォーラムでこの方法に対する批判に出くわしました。経験豊富なプログラマーが、そのような実装は言語レベルでは禁止されており、メモリー オーバーフローが避けられない(これはMetaTrader 4で常に発生していました)ため、一般的には不可能であると言いました。実際、MetaTrader 4の場合、この問題は解決できません。
ただし、MQL5では、ハンドルはチャート上の各インジケーターに対して一度作成され、必要に応じてアクセスされます。つまり、ティックごとに新しいハンドルを作成しても、新しく作成されるのではなく、既に作成されているハンドルにアクセスすることになります。これによってすでにメモリーにとっての負担が減ります。ただし、必要なすべてのハンドルを事前にOnInitで作成できるため、この問題については完全に忘れることができます。唯一の制限は、インジケーターを初期化するときに必要なすべてのハンドルを作成するために、期間が変更される制限内で事前に定義する必要があるという事実にあります。最大期間は、トレーダーがperiod_ma_maxパラメーターを介して設定で事前に制限します。ステップを使用すると、不要なハンドルの計算を回避することでさらに多くのメモリーを節約できます。ステップもトレーダーによって設定されます。デフォルト値は1です。
int OnInit() { //Create all necessary handles for(int i=1; i<=period_ma_max; i+=step) handle=iMA(_Symbol,_Period,i,0,method_MA,price_MA); }
次に、期間スクロールを実装するための機能を作成する必要があります。これをおこなうには、マウスホイールを使用して期間スクロールモードを有効にするオンチャートボタンを作成しましょう。
//+------------------------------------------------------------------+ //| CREATING BUTTON IN OnInit() //+------------------------------------------------------------------+ ObjectDelete(0,name); ObjectCreate(0,name,OBJ_BUTTON,0,0,0); ObjectSetString(chart_ID,name,OBJPROP_TEXT,text); ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr_Text_Button); ObjectSetInteger(chart_ID,name,OBJPROP_BGCOLOR,clr_Button); ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,CORNER_RIGHT_UPPER); ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,distance_X); ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,distance_Y); ObjectSetInteger(chart_ID,name,OBJPROP_XSIZE,size_X); ObjectSetInteger(chart_ID,name,OBJPROP_YSIZE,size_Y); ObjectSetInteger(chart_ID,name,OBJPROP_STATE,true); ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,true); ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,true); ObjectSetInteger(chart_ID,name,OBJPROP_STATE,press_Button); ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,1); ChartRedraw();
チャートに2つ以上のインジケーターをロードすると、それらのボタンが同じ場所に作成され、不便です。したがって、後続の各インジケーターを追加するときは、ボタンをなんらかの軸に沿ってシフトする必要があります。これをおこなうには、まずチャートにアップロードされたインジケーターの数を正確に計算する必要があります。まず、ウィンドウ内のインジケーターの総数を見つけてみましょう。
int total_Indicators=ChartIndicatorsTotal(0,0), this_indicators=0;
次に、それらからインジケーターを選択します。
for(int i=0; i<total_Indicators; i++) { if(ChartIndicatorName(0,0,i)=="Button_MA") this_indicators++; } IndicatorSetString(INDICATOR_SHORTNAME,"Button_MA")
この方法で短い名前でインジケーターを検索する場合、ループの後に短いインジケーター名を作成すると、チャートに追加する現在のインジケーターの名前がそのファイル名に対応することを常に覚えておく必要があります。この場合、ファイル名がINDICATOR_SHORTNAMEと異なる場合、ループ内の現在のインジケーターは計算されません。
次に、ボタンをX軸で移動します。
distance_X=size_X*this_indicators;
その後、チャートに追加されたすべてのインジケーターのボタンが一列に表示されます。残念ながら、1つのチャートに複数のインジケーターを追加する場合、ユーザーはボタンの名前を変更するか、少なくとも設定で他のインジケーター入力を変更する必要があります。これは、MetaTrader 5の1つのウィンドウに同じ入力を持つインジケーターを追加することが禁止されているために発生します。これに関してはどうしようもないので、設定の手動変更をトレーダーに任せる必要があります。設定の変更はオプションなので、ボタン名をインジケーターの設定に移動しましょう。これは一石二鳥です。インジケーターの入力を変更し、同じチャート上のオブジェクトに異なる名前を付けます。さらに、異なる名前のボタンは、より情報を含んでおり便利です。
input string name_Line = "MA_1"; string name = name_Line, text = name_Line;
ユーザーが各ボタンの名前を変更すると、インジケーターとボタン自体がウィンドウに簡単に追加され、ボタンに表示されるテキストがそれらの名前に対応するようになります。ボタンの準備が整いました。次に、期間をスクロールするためのメカニズムを作成する必要があります。ホイールスクロールイベントとマウスボタンクリックイベントをアクティブにします。
ChartSetInteger(0,CHART_EVENT_MOUSE_WHEEL,1); ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,1);
次に、OnChartEvent()関数で作業します。ボタンが押されているかどうかを確認します。押されていない場合は、その名前を表示します。ボタンが押されている場合、インジケーター期間をスクロールするモードを有効にし、チャート自体のスクロールを無効にします。同じように、ボタンが押されていない場合は、チャートのスクロールバックを有効にします。
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { //--- if(!press_Button) ObjectSetString(chart_ID,name,OBJPROP_TEXT,text); if(id==CHARTEVENT_OBJECT_CLICK) { if(sparam==name) { press_Button=ObjectGetInteger(chart_ID,name,OBJPROP_STATE); if(press_Button) { scroll_Button=true; ChartSetInteger(0,CHART_MOUSE_SCROLL,0); ChartRedraw(); } else { scroll_Button=false; ChartSetInteger(0,CHART_MOUSE_SCROLL,1); ChartRedraw(); } } } }
期間スクロールモードが有効になっている場合は、マウスホイールの状態を確認します。スクロール方向に応じて、期間を加算または減算します。合計ホイールスクロール値は、+120または-120に達するとトリガーされます。
if(scroll_Button) if(id==CHARTEVENT_MOUSE_WHEEL) { int delta = (int)dparam; if(delta>119) if(period_ma<period_ma_max) { period_ma+=step; ChartRedraw(); } // if(delta < -119) if(period_ma>step) { period_ma-=step; ChartRedraw(); }
ここで、新しい期間でインジケーターハンドルにアクセスし、インジケーターラインを再描画します(「total」はOnCalculateで定義されます)。また、ボタンのテキストを名前から現在の期間に変更します。
handle = iMA(_Symbol,_Period,period_ma,0,method_MA,price_MA); ArraySetAsSeries(Label1Buffer,true); for(int i = 0; i<total; i++) { double MA[]; CopyBuffer(handle,0,i,1,MA); Label1Buffer[i]=MA[0]; ChartRedraw(); } ArraySetAsSeries(Label1Buffer,false); if(press_Button) ObjectSetString(chart_ID,name,OBJPROP_TEXT,IntegerToString(period_ma)); }
ここでは、新しいティックが新しい期間のインジケーターラインを表示するのを待つ必要がないように、ラインを再描画します。したがって、新しいティックの到着に関係なく、ラインは常に即座に再構築されます。
避けられない別の制限は、ボタンに関するものです。ドラッグアンドドロップモードが有効な場合、ボタンを押すモードは無効になり、その逆も同様です。したがって、ボタンをより便利な場所に一度だけドラッグできます。ドラッグアンドドロップモードを無効にした後は、有効にしません。次の初期化中に、ボタンはその位置を記憶せず、一般的な行の元の場所に戻ります。
if(id==CHARTEVENT_OBJECT_CLICK) { if(sparam==name) { long select = ObjectGetInteger(chart_ID,name,OBJPROP_SELECTED); if(select==0) { ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,false); ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,false); flag_drag=false; } ChartRedraw(); } }
主なインジケーターラインはOnCalculate()で作成されます。いつものように
total=rates_total-1; if(Limit_for_Calc) if(total>Limit) total=Limit; handle = iMA(_Symbol,_Period,period_ma,0,method_MA,price_MA); if(handle==INVALID_HANDLE) { Print("invalid handle "); return(rates_total); } ResetLastError(); while(BarsCalculated(handle)<=0) { // indicator values are not calculated yet, try next time return(0); } for(int i = prev_calculated>0?prev_calculated-1:0; i<rates_total; i++) { double MA[]; CopyBuffer(handle,0,time[i],1,MA); Label1Buffer[i]=MA[0]+level; }ここでは、計算リソースを節約するために、最新のデータのみをスクロールするときにラインの計算を制限できます。これをおこなうには、設定で計算制限を有効にするかどうか、および計算に使用するバーの数をトレーダーに選択させます。
input bool Limit_for_Calc = false; input int Limit = 20000;
結果
インジケーター開発の要点を分析しました。その結果、標準インジケーターに決して劣らないより便利な本格的なインジケーターが得られます。しかしながら、まだいくつかの欠点があります。たとえば、バーの履歴が2万を超えるとを経験するスローダウンです。ただし、履歴分析はそれほど頻繁に必要とされるわけではなく、日常的に使用する計算のバーの数を制限できます。ボタンの名前を手動で変更したり、ボタンを複数回ドラッグできないこともかなり不便です。
一般的に、目標は達成されました。マウスホイールをスクロールすると、インジケーター期間がスムーズに変更されます。スクロール機能はチャートの右のボタンを1つ押すだけでオン/オフを切り替えられます。
結論
このようなインターフェイスは、欠陥がないわけではありませんが、標準のものよりも便利であると言えます。トレーダーは最小限の労力と時間で必要なインジケーターを設定し、ワークスペースから同じタイプのインジケーターを削除することができます。急速に変化する市場で限られた期間内により正確なシグナルを提供されます。
このようなインターフェイスを使用して作成されたインジケーターは、使いやすく、直感的で、時間を節約できます。取引に集中できるため、取引の質が向上し生産性が向上します。
さらに、このアプローチでは、期間だけでなく、ボタンまたはパネルに配置するその他の設定も使用できます。このような設定には、色、線幅、オブジェクトサイズなどが含まれる場合があります。スクロールに加えて、オブジェクトをドラッグしたり、ホットキーを使用したり、単にカーソルをオブジェクトやチャート エリアに合わせることができます。関数の1つはButton MAインジケーターに実装されています。ボタンを押すだけでなく、マウスを合わせるだけでも期間をスクロールできます。また、時間枠を変更しても、ドラッグ後にボタン位置が記憶されます。
この記事では、移動平均に基づく期間スクロールを備えたインジケーターを作成するための基本的な手順について説明しました。以下の添付ファイルでは、CCI に基づいた既製のインジケーターのコードを見つけることができます。1つのチャートのボタンはいくつあっても名前を変更する必要がないため、さらに簡潔になっています。それらの名前は、設定されたボタンの数に応じて自動的に索引付けされます。
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/10770
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索