【自動ロット管理】EnoughOrderPanel for MT5開発日記その②【注文ツール】

目的

前回に引き続きです。

現在自分の中では結構神ってる機能を持った注文ツールEnough Order PanelをMT5でも使いたい!と言う自分の要望の元進めていきます。

MT5にする唯一の理由としてFXGTさんによる仮想通貨取引が挙げられます。

為替は何となくpipsや損失利益は分かるようになりましたが、ビットコインなどの場合ロット数と利損の関係が曖昧です。

0.01ロットで100ドル動くと100円変動するところだけわかりました笑

昨今ビットコインが盛り上がってるので参加したいですよね?

桁数が多い場合に勘違いをしやすいのでどうしてもツール対応がしたかったです。

現状

FXGTさんのBTCUSDペアのみについてですが、基本的な機能が利用できるところまで来ました。

ロット管理、分割注文、sl設定、tp設定、建値設定、クリア、利益表示等。

最低限のラインとして自分で利用する上では問題ないところまで持ってこれたと思っています。

もう少しだけ調整したらMT5機能制限版もリリースを考えています。

簡単ですが以上です。

【自動ロット管理】EnoughOrderPanel for MT5開発日記その①【注文ツール】

EnoughOrderPanel概要

MT4版をテスト稼働させているEnoughOrderPanelですが、現在MT5対応版を開発中です。

機能に関してはMT4版を参考に見ていただくとして、なぜ開発しようかと考えたかというとFXGTさんでの仮想通貨取引や、株価指数取引で低ロットの取引が実現できるXMのMT5口座などで利用したかったからです。

シンプルにそれだけ、おそらく仮想通貨でのロット管理機能を備えている注文ツールは世界初になるんじゃないでしょうか?(大して調べていませんが)

MT4からMT5への移植

これがなかなか厄介な話になりまして、書き方のお作法が全然違います。

正確にいうと一部同様のコードは利用できますが、多くの場合書き直しになります。

いっそのこと共用で使えるコードにしたかったのですが、共用化のためのライブラリを一つずつ完成させていかないといけなかったために見送りに。

実際にどうやったのか?

最初に思い付いたのが、こちらの書籍のライブラリを利用すること方法も考えられます。

どうやら前提がEAとしてのライブラリのため、オブジェクト類が全滅、またオーダー類も固定の処理しかなかったため今回の移植にはいまいち利用できませんでした。

基本的な知識については非常に役に立つ書籍となっています。

で、今回覚えるのはこれだけ

#ifdef __MQL4__
//MT4での処理を記述
#endif

#ifdef __MQL5__
//MT5での処理を記述
#endif

以上です。

力技で処理を分岐させていきます。

面倒がってライブラリ化もしていなかったため、およそ5000行のコードをひたすら書き直し書き直し。
極力共用の処理にしたかったのですが、処理の検証等の時間も考えてひたすら力技で分岐していく作業。

mql5でのコンパイルエラーを確認し、エラー個所を修正、mql4での正常処理を確認といった感じに。

この作業の際にはこちらのコード対応表が非常に役立ちました。

現状表示とロット管理で数値が移動していること、通常の注文については動作すること確認しています。
まだpipsの内部処理、表示処理や、分割注文の処理などがうまく動作していないようなので、このあたりのを修正したらまた配布を考えています。

最終的にはコードの共通化をしてスマート化したいですが、まだまだ先のことになりそうです。
まずは動いただけでも良かったとしましょう。

続報をお待ちください。簡潔ですが以上となります。

【MT4】注文ツールを作成しようとしている話 その4~自動ロット管理・リスク管理~【mql4】

自動ロット管理・リスク管理機能

前回の続きの記事になります。


少し多忙でいまいち進捗が良くないため少し期間が空きました。

こちらに関しては声を大にして特筆する機能ではないと思っています。
標準的な2%ルール、5%ルールのような機能です。

エントリー時に合わせてsl設定位置をすることで最適なロットサイズを計算します。

大まかな処理

エントリー地点からsl位置までの値幅の損失が出た場合に、損失額が資金量の〇%になるように自動的にロットが調整されます。
資金管理についてはトレードの全体的に包括されるものであること、また自分が都度ロット計算をすることを手間に感じることから実装した機能になります

①Risk(%)欄にリスク割合を入力します。
②Risk(%)ボタンを押下します。(オンの場合はピンク色)
③画面に表示されている濃いピンク色のライン(sl)を移動します。
 ※この画面ですと成行注文になっていますが、もちろんほかの注文方法でも指値、逆指値でも利用できます。

処理としてはエントリー値、sl値の値幅に対して、資金量の指定したリスク割合のから適正ロットを割り出します。
イベント処理により、slラインやほかのラインを移動するごとに再計算しております。

特に珍しい処理でもないと思うので今回のコードについては割愛いたします。

テスター募集中

現在こちらの注文ツールについてテスターを募集しております。
開発中の物になるため、不具合等に理解がある方のみおねがいしております。

直接Discordに来ていただくか、下記のフォームにて応募ください。
連絡先としてメールアドレス、TwitterID、DiscordIDのいずれかは忘れずに入力をお願いいたします。

https://docs.google.com/forms/d/e/1FAIpQLSf37xfYB2WCgjnU9Z-8xrD3enY4Vt2pW6SmNnSbAPRB22lqzw/viewform?usp=sf_link

【MT4】注文ツールを作成しようとしている話 その3~特殊注文・戻成行・戻指値①~【mql4】

戻成行・戻指値とは

前回の続きの記事になります。

聞いたことのない注文方法だなと思った方はお察しの通り、「完全オリジナルの注文方法」になります。
長年実現したいと思っていた注文方法の一つです。

一言でいうと「目標とするラインをタッチしたときに注文を執行」します。
通常の指値や逆指値と変わらないと思うかもしれませんが、どこが違うのかというと、タッチしただけではなく「タッチ後に〇本以内に戻る」のならばという条件つきです。

少し名前にセンスがないので呼称に関してはもう少し検討中になります。

戻成行

分かりづらいのでもう少し戻り成行注文を掘り下げて説明すると
①現在USDJPYが99.8円です。
②100円で売りたいと思います。
③通常の指値の場合は100円にタッチしたらすぐにショート注文が約定されます。
④戻り成行の場合は100円にタッチした後に「5本以内に100円以下に戻るのならばショート注文」を約定させます。

上記の通り、この注文方法の構想は逆張り時のリスクを減らす注文方法となっております。
指値というものは絶対的に逆張りの注文となるため、指値をそのまま突き抜けてしまうといった事故が起こることが間々あります。
そのリスクを通常の指値注文よりも抑えるために実現したいと思っていた注文方法となります。

戻指値

同様に戻り指値注文に関してですが上記「④のタイミングで指値を配置する」ことができます。

例えば100円ラインをブレイクした際に99.2円まで戻るのならば場合買いたいと思っている場合、ブレイクラインを100円に設定、指値を99.2円に設定する。
この場合は順張りの注文となり、100円にタッチ後「5本以内に100円以下に戻るのならば99.2円に買い指値を配置」の様なよりリスクを抑えた通常ではできない様な注文方法を実現できます。
こちらは順張りの押し目買い、戻り売りをしたいときの注文方法になります。

実際の処理

世界中調べたわけではありませんがおそらく完全オリジナルな注文方法のため、テストしつつ実装している段階です。
現在の物は少し不都合があったため修正予定になりますが、Rボタンを押下すると戻成行用のエントリーラインをセットすることができます。

OnTickの中でエントリーラインと指定時間足の現在値を比較し、エントリーラインをCloseが超えた場合には買い注文フラグを立てます。
フラグが立っている状態で〇本以内にエントリーライン以下に戻るのを待ち戻った場合は注文を執行。
もしくは設定本数以上ローソク足が進んだ場合は期限切れキャンセルとなります。


もう一つの注文キャンセル方法としては、エントリー時に設定をしたslをエントリーラインを下回る前に超えた場合には注文キャンセルという処理を検討しております。
こちらについては現在実装前のため、構想のみです。


開発中のため変数設定もわかりづらいですがここで利用している「ReverseLimit」についてはローソク足の指定本数になります。

簡単にまとめると

①トリガーラインを超えたローソク足の時間を変数に入れる。

②ローソク足が進むごとに繰り返し、指定したローソクの本数を過ぎるまたはslを超えた場合に設定解除。

キャンセル処理に関しては最初の分岐点がオブジェクトの有無のため、オブジェクトの削除と注文方法のフラグのリセットだけになります。

   if(ObjectFind("reMarket") != EMPTY)
     {
      objrm = NormalizeDouble(ObjectGetDouble(0,"reMarket",OBJPROP_PRICE1),MarketInfo(Symbol(),MODE_DIGITS));
      if(High[1] < objrm && High[0] > objrm)
        {
         ReverseOrderFlag = -1;
         rm_time = iTime(Symbol(),5,0);
        }
      if(Low[1] > objrm && Low[0] < objrm)
        {
         ReverseOrderFlag = 1;
         rm_time = iTime(Symbol(),5,0);
        }
      rm_bars_shift = iBarShift(Symbol(),5,rm_time,true);
      if(ReverseLimit > rm_bars_shift && rm_bars_shift != -1 && rm_bars_shift != 0)
        {
         if(ReverseOrderFlag == -1)
           {
            for(int i = 1; i < ReverseLimit; i++)
              {
               if(Close[i] < objrm)
                 {
                  BtnOrderType = "Market";
                  lotSize = RoundDown(StringToDouble(ObjectGetString(0,"reMarkettext",OBJPROP_TEXT)),2);
                  OpenShortOrder();
                  ObjectDelete("reMarket");
                  ObjectDelete("reMarkettext");
                  ReverseOrderFlag = 0;
                 }
              }
           }
         else
            if(ReverseOrderFlag == 1)
              {
               for(int i = 1; i < ReverseLimit; i++)
                 {
                  if(Close[i] > objrm)
                    {
                     BtnOrderType = "Market";
                     lotSize = RoundDown(StringToDouble(ObjectGetString(0,"reMarkettext",OBJPROP_TEXT)),2);
                     OpenLongOrder();
                     ObjectDelete("reMarket");
                     ObjectDelete("reMarkettext");
                     ReverseOrderFlag = 0;
                    }
                 }
              }
        }
      else
         if(ReverseLimit <= rm_bars_shift)
           {
            ObjectDelete("reMarket");
            ObjectDelete("reMarkettext");
            ReverseOrderFlag = 0;
           }
     }

戻指値に関しても同様の処理となっていますが、同じ様に作成したため現在1本のラインがトリガーライン、エントリーラインを兼任しています。
当然ですが指値の場合はエントリーラインが執行時価格以上になるためエラーとなりますよね。
トリガーラインとエントリーラインを分けないといけないことを失念していたため、使いやすい様にGUI操作側での根本的な修正を検討しております。

今回のまとめ

言葉で説明するにはいまいち分かりづらい注文方法のため簡単に動画にまとめてお見せできないことが残念です。
私の中ではこれだけでも優位性があり面白い注文方法だと考えているため是非実装したく思っております。
もう少し仕様が煮詰まってきましたら再度解説と動画でお見せしてみたいと思います。
戻指値に関しては丸々処理の変更があると思いますので主に戻指値に関しての解説として検討しています。

それでは今回はこのあたりで終わります。

【MT4】注文ツールを作成しようとしている話 その2~特殊注文・フィボナッチエントリー~【mql4】

フィボナッチエントリーとは

また前回の続きの記事になります。
通常のエントリーの話をしても面白くないと思うので、特殊注文に触れてみようと思います。

タイトルの通りフィボナッチを利用したエントリーになります。
以前に書いた値幅計算の記事に基づいた分析をし、エントリーする時に便利に使える機能です。
具体的にどのような動きをしているのかというとフィボナッチエクスパンション(エクステンション)を利用し、指定した値幅位置にエントリーラインを移動させています。
これは非常によく使う手法のため、実現したかったエントリー方法の一つになります。

早速ですがどのようなシチュエーションで使うのか実例を挙げてみます。

分析 GBPUSD 2021/3/23

まずはトレーディングビューのチャートで分析をしています。(もちろんMT4上からでも問題ありません。)
下降5波動に対してのA波(上昇5波動)、B波(下降3波動)の様なものが認識できます。
C波が完成した後の下降を狙います。
チャートの形としてはこの後汚くなっているので想定通りの動きをするのかはわかりませんが、「1.40351」が「N値(1:1)」の値幅とわかります。

細かい話をするとエリオット波動の話になるため省きますが、この時点でN値を達成した場合そこから反落するんじゃないか?と考えることができます。

実際のエントリー

M-FuncTradePanelを利用してエントリーしてみましょう。
※開発中の画面です。

①F-Exをクリックすると2本の縦線が表示されます。(水色は右ラインを表示するオプションがオンの意味です)
②左のラインまたは右のラインを操作すると2本のラインの間にフィボナッチエクスパンションを引いてくれます。
③F-Exの右にある入力欄の数値の位置にエントリーラインを自動で移動します。またslは初期設定値幅を利用します。
④現在ショートを狙っている位置なので「Sell」をクリックします。

これで簡単にエントリーできましたね。

※動画上クリック位置がずれていますが、キャプチャーの都合です。
実際は正しい位置をクリックしております。

どんな処理をしているの?

ちょっと長いので省略しますが以下のようなイメージになります。

①縦ラインの範囲(左ラインのみ表示の場合は現在の足までの範囲)の高値、安値を探す。
②次点の高値もしくは安値を探す。(ここで3点が決まります。)
③3点目から1点目、2点目の値幅に倍数を掛けた値を足すもしくは引きます。

かいつまんでですがそんなイメージのコードです(要所要所)

if(id==CHARTEVENT_OBJECT_DRAG && (sparam == "FiboELeft" || sparam == "FiboERight"))
     {
      if(ObjectFind("Fibo-E") != EMPTY)
        {
         if(LowInd>HighInd)
           {
            ObjectDelete("Fibo-E");
            CreateFibonacciExpansion(chartid,"Fibo-E",Time[LowInd],LowPrice,Time[HighInd],HighPrice,Time[LowInd0],LowPrice0);
            FiboETime = Time[HighInd];
           }
         else
            if(LowInd<HighInd)
              {
               ObjectDelete("Fibo-E");
               CreateFibonacciExpansion(chartid,"Fibo-E",Time[HighInd],HighPrice,Time[LowInd],LowPrice,Time[HighInd0],HighPrice0);
               FiboETime = Time[LowInd];
              }
        }


      if(LowInd>HighInd)
         objen = LowPrice0+((HighPrice - LowPrice) * StringToDouble(ObjectGetString(0,_TextFeLevel,OBJPROP_TEXT)));
      if(LowInd<HighInd)
         objen = HighPrice0-((HighPrice - LowPrice) * StringToDouble(ObjectGetString(0,_TextFeLevel,OBJPROP_TEXT)));

      ChartRedraw();
      ObjectDelete("en");
      CreateTradeLine("en",objen,clrYellow,STYLE_SOLID);

      if(MarketInfo(Symbol(),MODE_BID) < objen)
         objsl = objen + PipsToPrice(StopLoss_Def);
      else
         objsl = objen - PipsToPrice(StopLoss_Def);
      ObjectDelete("sl");
      CreateTradeLine("sl",objsl,clrDeepPink,STYLE_SOLID);

      BtnOrderType = "Limit";
      ToggleButton(0,_BtnOrderLimit,1,clrPink,clrRed);
      ChartRedraw();
     }

今回のまとめ

自動でフィボナッチを引くことも可能なんですが、ジグザグベースやある範囲の高安ベースでその指定が難しいです。というか人間の思っているものと同じものになることは稀です。そのためラインで範囲を指定してその中から半自動で引いてくれる形にしました。

今後の展望

ここはまだまだ開発段階のものであり、今後の展望としては3点取れるためチャネルを引く拡張とリトレースメントの戻り範囲とエクスパンションの値幅位置が一致しているときのみエントリーできるようなエントリーロック、もしくはハイライト表示の様なものを考えております。

フィボナッチのラインごとに色を変えたく思っているのですが、どうやら1つのフィボナッチだけでは実現できなそうだったので、重ねてハイライト表示のみ別のオブジェクトとして処理をしようと思っていたりします。

このあたりについては実装しながら使いやすさを考えているのでどういう形に落ち着くかは未定です。

あくまで自分の使いやすいものを作っているつもりですが、やはりテスターさんなどがいると開発効率が上がったり案が増えたりしそうだなとは思ってます。

【MT4】注文ツールを作成しようとしている話 その1~機能整理・GUI~【mql4】

最初に計画しておきたいこと

前回の記事の続きになります。

今回は機能からGUIが生えてきました。

最初はGUIなんて作る予定もなく思い付きで作り始めたため、何をどこまで作り込むか全然計画を立てていなかったためとても苦労しました。

もしこの記事を見た後に作成する方は最初にざっくりでいいので「必要な機能の洗い出し」と「GUIの設計」をすることをお勧めします。

必要な機能の洗い出し

1度情報をするべくざっくり大枠でほしいと思った機能が以下の通り

  • 通常注文機能
  • 特殊注文機能(主にこれを作りたかった)
  • ポジション管理機能
  • ロット・リスク管理

機能の詳細はまた別記事で解説します。

GUIの設計・作成

Excelで設計図を作成

今回やらかした大きなことは作りながら考える、考えながら作る、あれもこれも作りたい・・・。

最初に形を考えずに欲しい機能欲しい機能と付けていったらあとから配置を変えるのが一苦労でした。

そのため一度スタートに戻って形から決めていきます。

いろんな描画ソフトで使いやすいものを試そうと思いましたが、調べたり覚えたり書いたりテストしたり全部自分でやっているためなかなか面倒です。

この時点で思った以上に大規模なプロジェクトになってまいりました。

そのため一番手軽に利用できそうなExcelをチョイス。

図形をセルに張り付く設定にして、ボタン類の配置を考えていきます。

またどのボタンがどのような挙動をするのかという洗い出しが必要になります。

オンオフトグルで切り替わるのか、押すと何かが変わるのか等・・・

理想でいうのならば「オブジェクトの種類」「変数名」「オブジェクトの挙動」「オブジェクトに与えられる機能」あたりも洗い出しておくと後々管理が楽でしょう。

実装してテストをしていくうちに使いやすい形が出てくると思うので最初はざっくり決めました。

GUIの作り方

大きく分けて通常のオブジェクトと標準ライブラリのDialogというものがあるようです。

もともと通常のオブジェクトとして作っていましたが、作り直しを考えている段階で標準機能としてGUIを作る事ができることに気づく。

試しに作ってみるが、慣れていないことと利用方法がイマイチ理解できず。

通常オブジェクトの場合は関数化して必要な値を与えることでボタン等が作成できるために工数が違いすぎる。

関数化できそうな事に気づくも構造体変数structの受け渡しが上手くできずに頓挫。

ネット上にもMT4でGUIを作るような資料は少なかったため後回しへ。

まだ全然理解できていませんがこのような感じで記述する必要がありそうです。

Create_LabelSymbolのほうが一般的にネット上で公開されている書式、Create_BtnTrapRepeatのほうが簡略化するために試行錯誤をしている形。

class CPanelDialog : public CAppDialog
  {
private:
  
   CLabel            m_LabelSymbol;
   CButton           m_BtnTrapRepeat; 

public:
                     CPanelDialog(void);
                    ~CPanelDialog(void);
   virtual bool      Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);

protected:
   bool              Create_LabelSymbol(void);
   bool              Create_BtnTrapRepeat(string name1, string name2, string text, double x1, double y1, double x2,double y2);
  };

bool CPanelDialog::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
  {
   if(!CAppDialog::Create(chart,name,subwin,x1,y1,x2,y2)) return(false);
   if( !Create_LabelSymbol())return (false);
      if(!Create_BtnTrapRepeat(
      "m_BtnTrapRepeat", "__BtnTrapRepeat", "Trap",
      indent_left,
      indent_top+full_height+controls_gap_y,
      indent_left+full_width,
      indent_top+full_height+controls_gap_y+full_height
   )) return(false);
   return(true);
  }

CPanelDialog AppWindow;

bool CPanelDialog::Create_LabelSymbol(void)
{
   int x1=indent_left;
   int y1=indent_top;
   int x2=x1+full_width;
   int y2=y1+full_height;
   
   if( !m_LabelSymbol.Create( m_chart_id, m_name + "m_LabelSymbol", m_subwin, x1, y1, x2, y2 ) ) return false;
   if( !m_LabelSymbol.Text( StringConcatenate(Symbol()," ",PERIOD_CURRENT)) ) return false;
   if( !Add( m_LabelSymbol ) ) return false;
   
   return true;
}

bool CPanelDialog::Create_BtnTrapRepeat(string name1, string name2, string text, double x1, double y1, double x2,double y2)
  {
   
   if(!m_BtnTrapRepeat.Create(0,name2,0,x1,y1,x2,y2)) return(false);
   if(!m_BtnTrapRepeat.Text(text)) return(false);
   if(!Add(m_BtnTrapRepeat)) return(false);

   return(true);
  }

これについては力技で並べていくか、記述する行数が違いすぎるためもう少し効率的なやり方が必要に思えます。

オブジェクト(ボタンやラベル)の作り方

苦労の末簡単な解決策はすぐに見つからなそうだったので、オブジェクトとして作成していくことに。

もともと途中まではオブジェクトで作成していったためつぎ足す形です。

最終的な配置については利用しながら使いやすさを考えていきます。

こういう感じで関数を作っておくとあとは必要な値を引数として渡すだけで作成ができます。

void CreateButton(string name, string label, int x, int y, int width, int height,
                  color bgColor = C'236,233,216', color textColor = clrBlack, int anchor = CORNER_RIGHT_UPPER)
  {
   ObjectCreate(name, OBJ_BUTTON, 0, 0, 0);
   ObjectSet(name,OBJPROP_XDISTANCE,x+width);
   ObjectSet(name,OBJPROP_YDISTANCE,y);
   ObjectSet(name,OBJPROP_WIDTH,x);
   ObjectSet(name,OBJPROP_XSIZE,width);
   ObjectSet(name,OBJPROP_YSIZE,height);
   ObjectSet(name, OBJPROP_CORNER, anchor);
   ObjectSet(name, OBJPROP_BGCOLOR, bgColor);
   ObjectSet(name, OBJPROP_COLOR, textColor);
   ObjectSet(name, OBJPROP_ZORDER, 100);
   ObjectSetText(name, label, FontSize);
  }

void CreateLabel(string name, string label, int x, int y, int width, int height,
                 color bgColor = C'236,233,216', color textColor = clrBlack, int anchor = CORNER_RIGHT_UPPER)
  {
   ObjectCreate(name, OBJ_LABEL, 0, 0, 0);
   ObjectSet(name,OBJPROP_XDISTANCE,x+width);
   ObjectSet(name,OBJPROP_YDISTANCE,y);
   ObjectSet(name,OBJPROP_WIDTH,x);
   ObjectSet(name,OBJPROP_XSIZE,width);
   ObjectSet(name,OBJPROP_YSIZE,height);
   ObjectSet(name, OBJPROP_CORNER, anchor);
   ObjectSet(name, OBJPROP_BGCOLOR, bgColor);
   ObjectSet(name, OBJPROP_COLOR, textColor);
   ObjectSet(name, OBJPROP_ZORDER, 100);
   ObjectSetText(name, label, FontSize);
  }

今回のまとめ

最初にも書きましたが機能の洗い出しとGUIの設計は必ず最初にやろうです。
後からGUIの配置を変えることは想像を絶するくらいに苦痛です。
また次回に続きます。

【MT4】注文ツールを作成しようとしている話 その0~準備編・自動建値~【mql4】

はじめに

※注意事項※

現在注文ツールを作成しており、技術的な部分を含めて不定期更新しようかと思っております。

作成中の記事につきバグなどがある可能性が十分にあるため、そのままのコードを利用したい場合は注意してください。

また、今までに作成したコードをそのまま利用していたり、ほかサイトのコードを参考に作成している場合があるためコーディングの仕方が統一されていない場合があります、ご了承ください。

何をしたかったのか?

もとはといえば何がしたかったのかというと、「全ての通貨ペアポジション」に対する「ポジション管理機能」が欲しかっただけ。

エントリー後のポジション管理が甘く利益になったポジションを損失にしてしまうことが多かったため、強制的に「自動建値」を入れる機能があればマイナスは防げるかなと思ったからです。

ググっても自分の理想とする挙動のものが見つからないため、自分で作成しようと思いました。

そこからですが、紆余曲折あり今までにやりたかった機能を実装して注文ツールとして形にしようと考えています。

自動建値の処理

メインの処理

  • エントリー位置から「設定閾値」を超えた場合に「設定建値値幅」にslを移動する機能。
  • 同時にロット数が「0.01」以上ならば半分利確する機能。
void OrderBuyEven(double point)
  {
   if(MarketInfo(OrderSymbol(), MODE_BID) - OrderOpenPrice() >= BeslAt * point)
     {
      if(OrderStopLoss() < OrderOpenPrice() && OrderStopLoss() != OrderOpenPrice() + Besl * point)
        {
         Print("建値+", Besl, " pips");
         if(OrderLots() > 0.01)
           {
            ticket = OrderClose(OrderTicket(), NormalizeDouble(OrderLots() / Trades, NormDigit), MarketInfo(OrderSymbol(),MODE_BID), slippage, CLR_NONE);
            Print("半利しました ",OrderSymbol()," - ",iClose(OrderSymbol(),0,0));
           }
        }
     }
void OrderSellEven(double point)
  {
   if(OrderOpenPrice() - MarketInfo(OrderSymbol(), MODE_ASK) >= BeslAt * point)
     {
      if(OrderStopLoss() > OrderOpenPrice() && OrderStopLoss() != OrderOpenPrice() - (Besl + spread)  * point)
        {
         Print("建値+", Besl, " pips");
         if(OrderLots() > 0.01)
           {
            ticket = OrderClose(OrderTicket(), NormalizeDouble(OrderLots() / Trades, NormDigit), MarketInfo(OrderSymbol(),MODE_ASK), slippage, CLR_NONE);
            Print("半利しました ",OrderSymbol()," - ",iClose(OrderSymbol(),0,0));
           }
        }
     }

欲しかった機能

通貨ペアごとに違う設定の閾値と、sl幅を設定できるようにしています。

現実的な用途を考えた場合ボラティリティが違うのに同一設定では使いづらいからという考えのもと設定値を増やしております。

細かくこれがこの設定と言うまで細分化はしてませんが、ある程度の区分けとして低ボラ通貨ペア、並ボラ通貨ペア、高ボラ通貨ペア、超ボラ通貨ペアと分けられるようにしています。

細かい処理は省きますが、簡単に説明します。

  • 設定値に変数としてカンマ区切りの通貨ペアを設定。
  • カンマ区切りにした変数を分割し配列に入れる。
  • 全ての注文状況を確認する。
  • それぞれオーダーの通貨ペアが配列の通貨ペアと一致した場合には予め設定してある個別設定を利用する。

という少し面倒な処理をしています。

            for(int i=0; i<ArraySize(PairList); i++)
              {
               if(OrderSymbol() == PairList[i])
                 {
                  BeslAt= BeslAt_Low * 10;
                  Besl= Besl_Low * 10;
                 }
              }

今回のまとめ

簡潔ですが今回はこのあたりまで。

まだ最終的な完成形ではないですが、少し違う形で機能ごとに無料公開を考えております。

もし詳細な情報を知りたい場合はこちらの記事やTwitter・Discordで質問をしていただくか、またはDiscordではリアルタイムで悩みながらコーディングをしているためそちらを参考にしていただければと思います。