
『市場での勘』を養う手段としてのベットのモデル化
はじめに
本稿はリアルタイムモードでのベットのモデル化のシンプルなメカニズムについて説明します。では、ベッティングとは何でしょうか?ファイナンシャル ベッティング-為替の後の変動(上昇または下降)を予測し、予測どおりにいけば資金を取得すること。(MetaQuotes Software Corp.ロシア語ウィキペディアから英語への翻訳)
実際、ベッティングにおいてわれわれが関心があるのは一つです。為替が上がるか下がるか、です。このときの変動ボリュームは重要ではありません。
小さなタイムフレームでのゲーム形式でベッティングをすれば、『市場での勘』を養うことができます。ペアが上がるか下がるか『見通す』ことを学ぶのです。本稿で説明するのはこれについてです。
概念
テクニカル分析、ファンダメンタル分析、資金管理のルール等を知ることは、トレーダーにとってひじょうに重要である、と言われます。明らかに、それはすべてひじょうに重要です。またいわゆる『市場での勘』も存在します。それはトレーダーがインディケータのない完全に明確なチャートを見るとき、どの方向に為替が動くかをおよそ知るものです。もちろん、この予測は常に正確とは限らず、エラーは毎回取引のたびに発生する可能性はあります。それでも、特に市場の状況を迅速に推定する必要があるときには、市場を『予見する』能力は非常に有用です。
通常、『市場での勘』は膨大な経験、数多くの実験の結果と言えます。そのような『実験』に費やされるものが何千USドルであることがひじょうに多いものです。
しかし、もっと時間も資金も使うことなくこの勘を養う方法がある、と私は思うのです。そんな方法のひとつがゲームを作成することです。その意味は、為替の変動方向を予測することです。現実の取引条件と連結していたら、そのゲームはもっと良いでしょう。実取引と連携することも可能なのです。
ヒトの能力は、明らかに鍛え養うことができます。絵画を描いたり、歌を歌ったり、楽器を演奏することを学ぶことができるのです。私は確かに、ヒトは市場を『見る』ことも同じように学習できると思います。コンピュータゲームをすることができるのです。同じように『市場の方向を予測する』ゲームをすることだってできます。ただし、ここで知るべきは、何から始め、この能力を伸ばすためにどうすればよいか、ということです。まずはゲームそのものが必要です。
タスク設定
では何が必要でしょうか?ゲームが必要です。それによってリアルタイムモードで実チャート上でプレーできるのです。また、このゲームはひじょうにシンプルなルールで実装が簡単でなければなりません。そして、実行される処理ではなく、市場自体に最大限の注意を払うものである必要があります。そのうえ、可能な実取引からあまり注意をそらすものであってはなりません。
ベッティングはこういった要件をすべて満たしているように思われます。ただそれは現実ではあまり都合のよいものではありません。そのような機会を提供している仲介会社は多くないのです。そのような仲介会社を見つけることができたとしても、なにか不都合があるものです。たとえば、デモアカウントが実取引から注意を反らせてしまう、などです。そうするとゲームは実アカウントにとって危険すぎると言えます。また、通常1時間未満の期間に対してベットすることはできません。
よって、このバリアントはわれわれのタスクに完全には適していないことがわかります。結果、このゲーム用に別のプログラムを書く必要があります。そのような制限のないプログラムです。MQL4 はわれわれの目的には理想的です。
実装
簡単な質問から始めます。それはどのように書くのでしょうか?明らかに、ユーザーは与えられる2つのバリアントから1つを選択します。それは上向きまたは下向きです(為替の将来の変動に関するユーザーの予測)。その後、推測が正しければプログラムは1ポイント追加し、誤っていれば1ポイント奪います。
選択の実装はオブジェクト SYMBOL_ARROWDOWN および SYMBOL_ARROWUP で行うのが良いでしょう。ユーザーはチャート上に必要な矢印を入れることもできるでしょう。ただし、それを描画し、署名を書くと時間もかかり、注意力も取られることとなるかもしれません。なので、このバリアントは適切ではありません。
もう一つのバリアントは新規ろうそく足の始めに矢印を2つ自動で設定することです。ユーザーは矢印を1つ削除し、残りはユーザーの推測を示すものとなります。その後、新規のろうそく足の始めで、Expert Advisor の予測が正しいかどうかをチェックするのです。そして、トータルスコアとして正しい推測数と誤った推測数がカウントされます。このために外部ファイルに記録を行います。
簡単そうですね。また簡単に実装できるのです。
//+------------------------------------------------------------------+ //| trener.mq4 | //| Copyright © 2008, FXRaider | //| | //+------------------------------------------------------------------+ #property copyright "Copyright © 2008, FXRaider" //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ extern int gap=5; int init() { //---- //---- return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- //---- return(0); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { //------------------------------ string solution="none"; int point, point_neg, point_pos; //------------------------------ //+---------------------------------------------------------------+ //| "up" choice searching | if( ObjectGet("up", OBJPROP_PRICE1)==Open[1]+gap*Point &&iBarShift(NULL,0,ObjectGet("up",OBJPROP_TIME1))==1 &&ObjectFind("down") != 0 &&ObjectFind("up") == 0 ) { solution="up"; } //| "up" choice searching | //+---------------------------------------------------------------+ //+---------------------------------------------------------------+ //| "down" choice searching | if( ObjectGet("down", OBJPROP_PRICE1)==Open[1]-gap*Point &&iBarShift(NULL,0,ObjectGet("down",OBJPROP_TIME1))==1 &&ObjectFind("up") != 0 &&ObjectFind("down") == 0 ) { solution="down"; } //| "down" choice searching | //+---------------------------------------------------------------+ //+---------------------------------------------------------------+ //| counting points at a positive answer | if((solution=="up"&&Open[1]<Close[1]) ||(solution=="down"&&Open[1]>Close[1])) { point=1; point_pos=1; point_neg=0; } //| counting points at a positive answer | //+---------------------------------------------------------------+ //+---------------------------------------------------------------+ //| counting points at a negative answer | if((solution=="up"&&Open[1]>Close[1]) ||(solution=="down"&&Open[1]<Close[1])) { point=-1; point_pos=0; point_neg=1; } //| counting points at a negative answer | //+---------------------------------------------------------------+ //+----------------------------------------------------------------------------------+ //| working with an external file | int handle; double points, //total score points_pos, //score of positive answers points_neg; //score of negative answers handle=FileOpen("trener_"+Symbol()+"_"+Period()+".csv", FILE_CSV|FILE_WRITE|FILE_READ,";"); if(handle>0) //if there is a file, read it { points=NormalizeDouble(StrToDouble(FileReadString(handle)),Digits); points_pos=NormalizeDouble(StrToDouble(FileReadString(handle)),Digits); points_neg=NormalizeDouble(StrToDouble(FileReadString(handle)),Digits); FileClose(handle); } if(solution!="none") //if a choice is made { handle=FileOpen("trener_"+Symbol()+"_"+Period()+".csv", FILE_CSV|FILE_WRITE|FILE_READ,";"); FileWrite(handle ,points+point); //write the total score FileWrite(handle ,points_pos+point_pos); //write the score of positive answers FileWrite(handle ,points_neg+point_neg); //write the score of negative answers FileClose(handle); } //| working with an external file | //+----------------------------------------------------------------------------------+ //+------------------------------------------------------------------------------------+ //| working with objects | if(iBarShift(NULL,0,ObjectGet("down",OBJPROP_TIME1))>0 ||ObjectGet("down",OBJPROP_PRICE1)!=Open[0]-gap*Point) { ObjectDelete("down"); } if(iBarShift(NULL,0,ObjectGet("up",OBJPROP_TIME1))>0 ||ObjectGet("up",OBJPROP_PRICE1)!=Open[0]+gap*Point) { ObjectDelete("up"); } if(ObjectFind("down") != 0&&ObjectFind("up") != 0) //if no object { ObjectCreate("down", OBJ_ARROW, 0, Time[0], Open[0]-gap*Point); //draw a down arrow ObjectSet("down", OBJPROP_STYLE, STYLE_DOT); ObjectSet("down", OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN); ObjectSet("down", OBJPROP_COLOR, Red); ObjectCreate("up", OBJ_ARROW, 0, Time[0], Open[0]+gap*Point); //draw an up arrow ObjectSet("up", OBJPROP_STYLE, STYLE_DOT); ObjectSet("up", OBJPROP_ARROWCODE, SYMBOL_ARROWUP); ObjectSet("up", OBJPROP_COLOR, Blue); } //| working with objects | //+------------------------------------------------------------------------------------+ Comment("Score: ", points," (",points_pos,"/",points_neg, //show the score ") | Time: ", Hour(),":", Minute(),":", Seconds());//show time (for convenience) //---- return(0); } //+------------------------------------------------------------------+
コードにはコメントが入っています。
それをチャートにアタッチしたら、以下の結果を取得します。
最後のバーに、上向きと下向きの矢印が2本あるのがわかります。左上角にはゲームのスコアと最終ティックのターミナル時刻が表示されています。スコアは3つの数字で表示されています。1番目はトータルスコア、2番目(括弧の中の1番目)は正の解答(正しい予測)、3番目(括弧内の2番目)は負の解答(誤った予測)です。時刻は「フルスクリーン」モード(F11)で操作しやすいように表示されています。
ゲームを『プレーする』には、ダブルクリック(デフォルト)で『不要な』矢印を選択し、「削除する」を押します(削除するには)。残っている矢印がわれわれの予測を示しています。
ここからは次のバーの始まりを待ちます。予測が正しければ、『スコア』は次のような形式になります:"Score: 1(1/0)"。予測が誤っていれば、『スコア』は次のような形式になります:"Score: -1(0/1)"。終値が始値に等しい場合は、スコアは変化しません。われわれの例では予測は誤りでした。
改善
タスクは達成されました。が、その実装にはデメリットがあります。最後の数秒も含め、ろうそく足形成の間ずっと選択をすることができるのです。これは不正に思えます。選択は最初の30秒の間に行う方がよいでしょう。そのためには、外部 int 変数 "time_limit" を取り入れます。その値は秒数と等しく、その間に選択が行われます。ユーザーがこの期間に選択できなければ、矢印はチャートから削除され、次のろうそく足にしか表示されません。
この変更は "working with objects"(説明はコメント内)の部分に書かれています。以下がそのコードです。
//+------------------------------------------------------------------+ //| trener.mq4 | //| Copyright © 2008, FXRaider | //| | //+------------------------------------------------------------------+ #property copyright "Copyright © 2008, FXRaider" //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ extern int gap=5; extern int time_limit=30; int init() { //---- //---- return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- //---- return(0); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { //------------------------------ string solution="none"; int point, point_neg, point_pos; //------------------------------ //+---------------------------------------------------------------+ //| "up" choice searching | if( ObjectGet("up", OBJPROP_PRICE1)==Open[1]+gap*Point &&iBarShift(NULL,0,ObjectGet("up",OBJPROP_TIME1))==1 &&ObjectFind("down") != 0 &&ObjectFind("up") == 0 ) { solution="up"; } //| "up" choice searching | //+---------------------------------------------------------------+ //+---------------------------------------------------------------+ //| "down" choice searching | if( ObjectGet("down", OBJPROP_PRICE1)==Open[1]-gap*Point &&iBarShift(NULL,0,ObjectGet("down",OBJPROP_TIME1))==1 &&ObjectFind("up") != 0 &&ObjectFind("down") == 0 ) { solution="down"; } //| "down" choice searching | //+---------------------------------------------------------------+ //+---------------------------------------------------------------+ //| counting points at a positive answer | if((solution=="up"&&Open[1]<Close[1]) ||(solution=="down"&&Open[1]>Close[1])) { point=1; point_pos=1; point_neg=0; } //| counting points at a positive answer | //+---------------------------------------------------------------+ //+---------------------------------------------------------------+ //| counting points at a negative answer | if((solution=="up"&&Open[1]>Close[1]) ||(solution=="down"&&Open[1]<Close[1])) { point=-1; point_pos=0; point_neg=1; } //| counting points at a negative answer | //+---------------------------------------------------------------+ //+----------------------------------------------------------------------------------+ //| working with an external file | int handle; double points, //total score points_pos, //score of positive answers points_neg; //score of negative answers handle=FileOpen("trener_"+Symbol()+"_"+Period()+".csv", FILE_CSV|FILE_WRITE|FILE_READ,";"); if(handle>0) //if there is a file, read it { points=NormalizeDouble(StrToDouble(FileReadString(handle)),Digits); points_pos=NormalizeDouble(StrToDouble(FileReadString(handle)),Digits); points_neg=NormalizeDouble(StrToDouble(FileReadString(handle)),Digits); FileClose(handle); } if(solution!="none") //if a choice is made { handle=FileOpen("trener_"+Symbol()+"_"+Period()+".csv", FILE_CSV|FILE_WRITE|FILE_READ,";"); FileWrite(handle ,points+point); //write the total score FileWrite(handle ,points_pos+point_pos); //write the score of positive answers FileWrite(handle ,points_neg+point_neg); //write the score of negative answers FileClose(handle); } //| working with an external file | //+----------------------------------------------------------------------------------+ //+------------------------------------------------------------------------------------+ //| working with objects | if(iBarShift(NULL,0,ObjectGet("down",OBJPROP_TIME1))>0 ||ObjectGet("down",OBJPROP_PRICE1)!=Open[0]-gap*Point) { ObjectDelete("down"); } if(iBarShift(NULL,0,ObjectGet("up",OBJPROP_TIME1))>0 ||ObjectGet("up",OBJPROP_PRICE1)!=Open[0]+gap*Point) { ObjectDelete("up"); } int sec_lim; if(!time_limit) { sec_lim=0; } else { sec_lim=TimeCurrent()-time_limit; } if(sec_lim>ObjectGet("up",OBJPROP_TIME1) &&sec_lim>ObjectGet("down",OBJPROP_TIME1) &&ObjectFind("down") == 0&&ObjectFind("up") == 0 &&iBarShift(NULL,0,ObjectGet("down",OBJPROP_TIME1))==0 &&iBarShift(NULL,0,ObjectGet("up",OBJPROP_TIME1))==0) { ObjectDelete("up"); ObjectDelete("down"); } if((ObjectFind("down") != 0&&ObjectFind("up") != 0) //if no objects &&sec_lim<Time[0]) { ObjectCreate("down", OBJ_ARROW, 0, Time[0], Open[0]-gap*Point); //draw a down arrow ObjectSet("down", OBJPROP_STYLE, STYLE_DOT); ObjectSet("down", OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN); ObjectSet("down", OBJPROP_COLOR, Red); ObjectCreate("up", OBJ_ARROW, 0, Time[0], Open[0]+gap*Point); //draw an up arrow ObjectSet("up", OBJPROP_STYLE, STYLE_DOT); ObjectSet("up", OBJPROP_ARROWCODE, SYMBOL_ARROWUP); ObjectSet("up", OBJPROP_COLOR, Blue); } //| working with objects | //+------------------------------------------------------------------------------------+ Comment("Score: ", points," (",points_pos,"/",points_neg, //show the score ") | Time: ", Hour(),":", Minute(),":", Seconds());//Show time (for convenience) //---- return(0); } //+------------------------------------------------------------------+
これで、入力パラメータの中に変更可能な変数を2つ取得しました。
パラメータ "gap" はポイント数を示します。それは矢印とろうそく足の始値の間の距離です。変数 "time_limit" は秒数を示します。その間にユーザーは選択を行うのです。その値が "0" であれば、時間制限はない、すなわちろうそく足が形成される間ずっと選択を行うことが可能です。
おわりに
MQL4 言語によりファイナンシャルベッティングのシンプルバージョンを実装しました。このゲームは市場を『予見する』能力を大きく養うことに役立ち、また為替変動の数多くの規則性を学ぶのにも助けとなります。このバージョンは、トレーダーの注意が最大限価格チャートに集中するように実装されています。トレーダーにより実行される処理には、最低限の時間が必要なだけで、理解がしやすくなっています。
私は自分のゲームの結果をシェアしたいと思います。連続して5~10のろうそく足に対して正しい予測をすることができました(5分足チャートで)。
このゲームを使用して、トレーダーはもっとも重要な質問の1つに答える方法を学ぶことができます。その質問とは、「為替はどこで変動するのか?」です。まだまだ重要な質問は他にもあります。利益固定、損失固定、トレードをオープンするボリューム選択、等です。これら質問のすべてに答える方法を知って初めてトレーダーは安定した結果を出すようになるのです。
その他重要な質問の1つはトレーダーの休憩時間です。このゲームはエンターテイメント市場の既存ゲームの中でもっとも有用なゲームかもしれません。
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/1505



- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索