ここでは、値幅を全て%(パーセンテージ)で算出して決済するEAを作成していきます。
EAでの取引の概要
決済条件
決済条件は、下記の3つです。
・損切り(ストップロス)は、エントリー価格の〇%
・利益確定(テイクプロフィット)はエントリー価格の〇%
・最大含み益の〇%でトレーリングストップ
上昇率と下落率の違い
100円の物の価格が1日10%ずつ上昇した場合、元の価格から100%上昇(200円)になるのにかかる日数は次の通りです。
当日 100円
1日後 110円
2日後 121円
3日後 133.1円
4日後 146.41円
5日後 161.051円
6日後 177.1561円
7日後 194.87171円
8日後 214.358881円
100円の物の価格が1日10%ずつ下落した場合、元の価格から100%下落(0円)になるのにかかる日数は次の通りです。
当日 100円
1日後 90円
2日後 81円
3日後 72.9円
4日後 65.61円
5日後 59.049円
6日後 53.1441円
7日後 47.82969円
8日後 43.046721円
9日後 38.7420489円
10日後 34.86784401円
11日後 31.38105961円
12日後 28.24295365円
1日10%ずつ変動した場合、上昇方向は8日後に100%上昇に到達しますが、下落方向は永久に100%下落には到達しません。
以上のことから、買い取引と売り取引を別々に検証する必要があるので、今回のEAは買いエントリーのみのEAとします。
エントリー条件
決済ロジックの優位性を判断するために、エントリータイミングは、ローソク足の始値時点で〇分の1の確率で買いエントリーとします。
EAを作成
今回のEAの完成形を確認
今回作成するEAのコードがこちら。解説はその後するぞい!
extern double StopLossPer = 2.0; extern double TakeProfitPer = 5.0; extern double TrailingStartPer = 2.0; extern double TrailingStopPer = 50; extern double Lots = 0.1; extern int MagicNumber = 20191113; extern int Probability = 100; int OnInit() { MathSrand(GetTickCount()); // 乱数のシード設定 return(INIT_SUCCEEDED); } void OnTick() { int i, ticket; double sl, tp, ts; // 保有ポジションを確認 ------------------------------- int pos_ticket = 0; for (i=0; i<OrdersTotal(); i++) { if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) return; if (OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNumber) continue; pos_ticket = OrderTicket(); break; } // ポジション保有時の処理 ----------------------------- if (pos_ticket > 0) { if (OrderSelect(pos_ticket, SELECT_BY_TICKET) == false) return; // トレーリングストップ sl = NormalizeDouble(OrderStopLoss(), Digits); if (Bid >= OrderOpenPrice() * (100 + TrailingStartPer) * 0.01) { ts = NormalizeDouble(OrderOpenPrice() + (Bid - OrderOpenPrice()) * TrailingStopPer * 0.01, Digits); if (sl == 0 || sl < ts) if (OrderModify(OrderTicket(), 0, ts, OrderTakeProfit(), 0, clrRed) == false) Print("OrderModify error."); } } // エントリーシグナル生成 ----------------------------- int sign = -1; static datetime sign_check_time = 0; if (sign_check_time != Time[0]) { sign = MathRand() % Probability; sign_check_time = Time[0]; } // ポジション無しの時の処理 --------------------------- if (pos_ticket == 0) { // エントリー if (sign == 0) { sl = 0; tp = 0; if (StopLossPer > 0) sl = NormalizeDouble(Ask - Ask * StopLossPer * 0.01, Digits); if (TakeProfitPer > 0) tp = NormalizeDouble(Ask + Ask * TakeProfitPer * 0.01, Digits); ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, 0, sl, tp, NULL, MagicNumber, 0, clrBlue); } } }
今回のEA【Sample_PercentClose_EA.mq4】をダウンロード
パラメーター設置
必要パラメーターのコードをOnInit()関数の上あたりに追加します。
extern double StopLossPer = 2.0; extern double TakeProfitPer = 5.0; extern double TrailingStartPer = 2.0; extern double TrailingStopPer = 50; extern double Lots = 0.1; extern int MagicNumber = 20191113; extern int Probability = 100;
StopLossPer | 損切幅 % |
---|---|
TakeProfitPer | 利食い幅 % |
TrailingStartPer | トレーリング開始幅 % |
TrailingStopPer | トレーリング幅 % |
Lots, MagicNumber | ロット数, マジックナンバー |
Probability | エントリー確率 1/〇 |
OnInit()関数内
OnInit()関数内には、次のように乱数のシードを設定しておきます。
MathSrand(GetTickCount()); // 乱数のシード設定
OnTick()関数内
OnTick()関数内では、次のような構成にします。
・よく使う変数を宣言
・保有ポジションを確認
・ポジション保有時の処理
・エントリーシグナル生成
・ポジション無しの時の処理
保有ポジションを確認
今回は、買いポジションしか保有しないので次のコードのように、OrderType()関数で取引種別を判定せずに保有ポジションを確認しています。
int pos_ticket = 0; for (i=0; i<OrdersTotal(); i++) { if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) return; if (OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNumber) continue; pos_ticket = OrderTicket(); break; }
ポジション保有時の処理
ポジション保有時の処理として、次のコードのように、トレーリングストップの処理を行います。
if (pos_ticket > 0) { if (OrderSelect(pos_ticket, SELECT_BY_TICKET) == false) return; // トレーリングストップ sl = NormalizeDouble(OrderStopLoss(), Digits); if (Bid >= OrderOpenPrice() * (100 + TrailingStartPer) * 0.01) { ts = NormalizeDouble(OrderOpenPrice() + (Bid - OrderOpenPrice()) * TrailingStopPer * 0.01, Digits); if (sl == 0 || sl < ts) if (OrderModify(OrderTicket(), 0, ts, OrderTakeProfit(), 0, clrRed) == false) Print("OrderModify error."); } }
エントリーシグナル生成
ポジションの有無にかかわらず、次のコードのように、ローソク足の始値時点でエントリーシグナルを生成させます。
int sign = -1; static datetime sign_check_time = 0; if (sign_check_time != Time[0]) { sign = MathRand() % Probability; sign_check_time = Time[0]; }
ローソク足の始値時点で、変数signが0~Probability-1の値になるようにしています。
ポジション無しの時の処理
ポジション無しの時の処理として、シグナル判定からのエントリー注文をしています。
if (pos_ticket == 0) { // エントリー if (sign == 0) { sl = 0; tp = 0; if (StopLossPer > 0) sl = NormalizeDouble(Ask - Ask * StopLossPer * 0.01, Digits); if (TakeProfitPer > 0) tp = NormalizeDouble(Ask + Ask * TakeProfitPer * 0.01, Digits); ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, 0, sl, tp, NULL, MagicNumber, 0, clrBlue); } }
あとがき
価格に対するパーセンテージや、利益幅に対するパーセンテージの算出方法を解説しながらEAを作成しましたが、参考になりましたでしょうか?
不明な点などがあったらお気軽にコメントください^^
次回は、今回のEAにトレーリングストップ発動条件を追加します。