<!-- markdown -->

# MT5のEAの学習メモ

[TOC]

# なぜMT4ではなくMT5なのか?
デイトレするときにポジションをまとめてクローズすることができていいよ。と知人におしえてもらったからです。詳しいことはこれから勉強します。

# MT5ダウンロード
以下の証券会社から無料でダウンロードできます。いまのところ日本の証券会社はMT4だけの場合が多い印象です。

EXNESSはオーストラリアの会社?だそうです。間違ってたらすいません。

https://exn.fxsignup.com/trading-tool/

住所の証明がちょっと大変でした。免許書と公共料金の支払いの紙が証明で必要でした。

# 移動平均を使った売買
はじめてMQT5でEAを作ってみました。

移動平均のクロスでエントリーして、ストップロスと、テークプロフィットを決めるロジックです。

いろいろ、間違っています。はい。

パラメータは、日足でUSD/JPYでよさげになるように調節してあります。

    #property copyright "Copyright 2023, Hayashi Kuniyuki"
    #property link      "https://java.boy.jp/pukiwiki/index.php?MT5%20EA"
    #property version   "1.00"
    #property strict
    //+------------------------------------------------------------------+
    //| Include                                                          |
    //+------------------------------------------------------------------+
    #include <Trade\trade.mqh>
    
    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    
    // グローバル変数の宣言
    input double inpLotSize = 0.1;       // 注文のロットサイズ
    input int inpMagicnumber = 20231006; // マジックナンバー
    input double inpStopLoss = 100; // ストップロスのpips
    input double inpTakeProfit = 700; // 利確のpips
    
    input int inpShortSmaPeriod = 3; // 移動平均の短い期間
    input int inpLongSmaPeriod = 5; // 移動平均の長い期間
    
    
    // ポジションについての情報
    struct Posi {
       datetime openTime; // 二重登録防止用
       double price; // 注文価格
       double stopLoss; // ストップロス
       double takeProfit; // 利確
       bool needRetry; // 取引失敗時のリトライ管理
       int sign; // 計算用 1 or -1
       ENUM_POSITION_TYPE posi_type;
       ENUM_SYMBOL_INFO_DOUBLE symbol_type;
       ENUM_ORDER_TYPE order_type;
    };
    Posi posiBuy = {0, 0, 0, 0, false, 1, POSITION_TYPE_BUY, SYMBOL_ASK, ORDER_TYPE_BUY}; // 買いポジション管理
    Posi posiSell = {0, 0, 0, 0, false, -1, POSITION_TYPE_SELL, SYMBOL_BID, ORDER_TYPE_SELL}; // 売りポジション管理
    
    // 移動平均の構造体
    struct Sma {
       int period; // 期間
       int handle; // ハンドル
       double prices[]; // 直近とその前の値
    };
    Sma smaShort; // 短い期間の移動平均
    Sma smaLong; // 長いほうの期間の移動平均
    
    CTrade trade; // 取引実行インスタンス
    
    int OnInit() {
       // ユーザ入力チェック
       if (inpLotSize <= 0 || inpLotSize >= 1) {
          Alert("inpLotSize <=0 || inpLotSize >= 1 ");
          return INIT_PARAMETERS_INCORRECT;
       }
       
       if (inpStopLoss <= 0 || inpStopLoss >= 1000) {
          Alert("inpStopLoss <= 0 || inpStopLoss >= 1000");
          return INIT_PARAMETERS_INCORRECT;
       }
       
       if (inpTakeProfit <= 0) {
          Alert("inpTakeProfit <= 0");
          return INIT_PARAMETERS_INCORRECT;
       }
       
       if (inpShortSmaPeriod <= 0) {
          Alert("inpShortSmaPeriod <= 0");
          return INIT_PARAMETERS_INCORRECT;
       }
       
       if (inpLongSmaPeriod <= 0) {
          Alert("inpLongSmaPeriod <= 0");
          return INIT_PARAMETERS_INCORRECT;
       }  
       
       if (inpLongSmaPeriod <= inpShortSmaPeriod) {
          Alert("inpLongSmaPeriod <= inpShortSmaPeriod");
          return INIT_PARAMETERS_INCORRECT;
       }         
       
       // Sma設定
       setSma(smaShort,inpShortSmaPeriod);
       setSma(smaLong,inpLongSmaPeriod);
        
       return(INIT_SUCCEEDED);
    }
    
    void OnDeinit(const int reason){
       // メモリ解放
       releaseSma(smaShort);
       releaseSma(smaLong);
    }
    
    void OnTick() {
       // 価格取得
       if (!fetchPrice(smaShort)) return;
       if (!fetchPrice(smaLong)) return;
       
       // 買いポジションを取る
       if (posiBuy.needRetry) {
          openPosi(posiBuy);
       }
       if (isCrossOver(smaShort.prices, smaLong.prices) && !hasPosition(posiBuy)) {
          Print("ゴールデンクロス");
          posiBuy.needRetry = true;
          openPosi(posiBuy);
          dump(smaShort);
          dump(smaLong);
       }
    
       // 売りポジションを取る
       if (posiSell.needRetry) {
          openPosi(posiSell);
       }   
       if (isCrossOver(smaLong.prices, smaShort.prices) && !hasPosition(posiSell)) {
          Print("デッドクロス");
          posiSell.needRetry = true;
          openPosi(posiSell);
          dump(smaShort);
          dump(smaLong);
       }  
    }
    
    
    //+------------------------------------------------------------------+
    //| Utility                                                          |
    //+------------------------------------------------------------------+
    // 移動平均の初期化
    void setSma(Sma &sma, int period) {
       sma.period = period;
       sma.handle = iMA(_Symbol, PERIOD_CURRENT, period, 0, MODE_SMA, PRICE_CLOSE);
       ArraySetAsSeries(sma.prices, true);
    }
    
    // インジケータをメモリから解放
    void releaseSma(Sma &sma) {
       if (sma.handle != INVALID_HANDLE) {IndicatorRelease(sma.handle);} 
    }
    
    // 移動平均の現在値とひとつ前の値取得
    bool fetchPrice(Sma &sma) {
       int arraySize= CopyBuffer(sma.handle, 0, 0, 2, sma.prices);
       if (arraySize != 2) {
          Print("移動平均のデータが十分ではない。");
          return false;
       }
       return true;
    }
    
    // 交わっているか判定
    bool isCrossOver(double &prices1[], double &prices2[]) {
       return ((prices1[1] <= prices2[1]) && (prices1[0] > prices2[0]));
    }
    
    // Tickの現時間取得
    datetime now() {
       return iTime(_Symbol,PERIOD_CURRENT,0);
    }
    
    // ポジション持っているか
    bool hasPosition(Posi &posi) {
       return (posi.openTime == now());
    }
    
    // ポジションを持つ
    void openPosi(Posi &posi) {
       double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
       posi.price = SymbolInfoDouble(_Symbol, posi.symbol_type);
       posi.stopLoss = posi.price - (posi.sign * inpStopLoss * symbolPoint );
       posi.takeProfit = posi.price + (posi.sign + inpTakeProfit * symbolPoint ); 
       
       Print("symbolPoint: ", symbolPoint, ", price: ", posi.price, ", st: ", posi.stopLoss, " tp: ", posi.takeProfit);
       
       // ポジションをもてなければリトライフラグを取り下げない
       if (trade.PositionOpen(_Symbol, posi.order_type,inpLotSize,posi.price, posi.stopLoss, posi.takeProfit,"cross EA")){
          posi.needRetry = false;
       }
       posi.openTime = now();
       
    }
    
    // 確認用
    void dump(Sma &sma){
       Print("[0]: ", sma.prices[0], ", [1]: ", sma.prices[1]," :Sma" , sma.period);
    }

# クラスも作成できる
    class CSomethingClass{
      public:
        int number;
    };

インスタンスの生成例
    CSomethingClass somethingClass;

クラスの配列の作成例
    CSomethingClass somethingClass[];

要素を追加するには
    ArrayResize(somethingClass, ArraySize(somethingClass) + 1);

# Scriptの作成
ちょっとしたチャート上でよくやる操作は、Sciptとして作成し、ショートカットで呼び出すと便利です。

## 取引履歴のトグル表示
まだ、確認画面がでる点がスマートではないですが、チャートの表示状態の取得と変更のサンプルにはなるでしょう。
    //+------------------------------------------------------------------+
    //|                                       ToggleShowOrderHistory.mq5 |
    //|                                 Copyright 2023, Hayashi Kuniyuki |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2023, Hayashi Kuniyuki"
    //+------------------------------------------------------------------+
    //| Script program start function                                    |
    //+------------------------------------------------------------------+
    #property script_show_inputs
    #property strict
    //+------------------------------------------------------------------+
    //| Script program start function                                    |
    //+------------------------------------------------------------------+
    void OnStart() {
       // Get the current chart ID
       long chartID = ChartID();
    
       // Check the current state of 'Show trade history' property
       bool showTradeHistory = ChartGetInteger(chartID, CHART_SHOW_TRADE_HISTORY);
    
       // Toggle the 'Show trade history' property
       showTradeHistory = !showTradeHistory;
       ChartSetInteger(chartID, CHART_SHOW_TRADE_HISTORY, showTradeHistory);
    
       // Notify the user of the change
       if(showTradeHistory)
          Print("Trade history is now displayed.");
       else
          Print("Trade history is now hidden.");
    }

## チャートテンプレートを適用するコード
チャートのテンプレートをショートカットで切り替えれるようになると便利です。
    //+------------------------------------------------------------------+
    //|                                 Copyright 2023, Hayashi Kuniyuki |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2023, Hayashi Kuniyuki"
    input string templateName = "xxx"; // 使用したいテンプレート名
    
    //+------------------------------------------------------------------+
    //| Script program start function                                    |
    //+------------------------------------------------------------------+
    void OnStart()
    {
       // インジケータのテンプレートを読み込む
       ChartApplyTemplate(0, templateName + ".tpl");
    }

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   最終更新のRSS