ここでは、値幅を全て%(パーセンテージ)で算出して決済する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の完成形を確認
Dr.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にトレーリングストップ発動条件を追加します。






