【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ではリアルタイムで悩みながらコーディングをしているためそちらを参考にしていただければと思います。

【無料】AutoBreakEven(自動建値)【MT5】

更新情報

2021/6/13 現在EnoughOrderPanelに寄せたモノに修正中です。
開発中に画面ですが、自動建値、建値設定ボタン、自動ロット管理の機能を考えています。

※開発中の画面になります。

目的・動作

2021年ビットコインが盛り上がっていますね。

通常のトレードと同様にMT5を使って日本円の証拠金でトレードのできる「FXGT」をご存じですか?

普段と同じ操作で利用ができる・・・とはいってもどうしてもビットコインのボラティリティは気になるもの。

エントリーしたのに見ていない間にすぐにslにかかったりしてしまいますよね。

FXGT」の「BTSUSD」取引にて安全性を高めるべく、自動で建値に設定できるEAがあれば便利かと思いました。

全てのポジション」に対しての管理をするものが見つからなかったため作成しました。

自宅PCやVPSなどで動作しておくことにより、外出中のスマホからのエントリー等の見れない時間帯にエントリーした場合でもポジションの管理をする事が目的です。

特定のポジションだけ操作する機能はありません。

動作上の注意

あくまで個人で利用するために作成したものなので予期しないバグやエラーが存在しているかもしれません。

注文の変更をする機能のため自己責任での利用の元必ず最初は「小ロット」かつ「画面を見れる環境」で確認をしながら利用してください。

なお「FXGT」の「BTCUSD」以外でテストはしていません。

全てのポジションに対しての操作をすることからほかの通貨ペアが対象でも意図しない動作をすると思うのでお気を付けください。

簡単に治るようなバグなどがありましたら修正します。

設定値

①建値($表記)→建値を注文価格の±「$5」の位置に設定。

②閾値($表記)→エントリー位置から「$30」進んだ際に①のsl建値設定を実行。

③ラインの表示→②の閾値ラインを表示します。

事前にこのあたりで建値設定されるんだなと目安に。

(価格と一緒に移動するので基本は設定値の確認用)

動作イメージ

この例だと各ポジションの「$10」の位置に建値を設定している。

ダウンロードリンク
AutoBreakEven_MT5