ナンピンマーチンEAのロジックにおいて、ナンピン幅の設定と同時に基本となるのは、ロット数をどの程度増加させていくかというマーチン倍率の設定です。
マーチンゲール法といえば基本は倍率2倍なのかもしれませんが、1.5倍というのもナンピンマーチンEAではよく採用されています。
その他、ココモ法と言って、単純に前のロット数の定数倍とかではない方法も考えられます。
この記事では、ココモ法の導入方法を含め、ナンピンマーチンEAのロット数の設定機能拡張方法についてご紹介します。
EAのベースモデル
ここでは、以下の記事で作成したEAを「ベースモデル」と呼んで、機能追加を行なっていきます。
最も単純なナンピンマーチンEAをゼロから作成する記事になっていますので、まだご覧になっていない方は是非一度ご確認ください。
Inputの設定
ベースモデルでは、以下のインプット項目を設定していました。
input double first_lot = 0.01;//初期ロット
input double nanpin_range = 200;//ナンピン幅
input double profit_target = 143;//利益目標
input int magic_number = 10001; //マジックナンバー
static int ticket_number;//チケットナンバー
double slippage = 10;//スリッページ
ここにさらに、lot数パターンのインプット項目を追加します。
input int lot_type = 1;//lot数パターン(1:マーチン1.5倍、2:マーチン2倍、3:ココモ法)
lot数パターン(lot_type)
ナンピン注文におけるlot数をどのようにするかという設定を使い分けるための変数を設定しておきます。
ここでは、
- マーチン倍率 1.5倍
- マーチン倍率 2倍
- ココモ法
の3パターンを選択出来るように設定しました。
ループ処理
事前に必要は追加処理が終わり、ここからループ処理の中の機能追加に入ります。
void OnTick()
void OnTick()
{
これ以降は、void OnTick()の中に追加記載していく内容になります。
変数の定義
ベースモデルでは、以下の変数を定義していました。
int cnt;
int current_buy_position;//最新のbuyポジション
int current_sell_position;//最新のsellポジション
int buy_position;//buyポジション数
int sell_position;//sellポジション数
double buy_profit;//buyポジションの含み損益
double sell_profit;//sellポジションの含み損益
ここに、以下の5つの定義を追加します。
double current_buy_lot;//最新のbuyポジションのlot数
double current_sell_lot;//最新のsellポジションのlot数
double pre_buy_lot;//一つ前のbuyポジションのlot数
double pre_sell_lot;//一つ前のsellポジションのlot数
double nanpin_lot;//ナンピン注文のlot数
current_buy_lot、current_sell_lot
current_buy_lotは、最新のbuyポジションのlot数を記録しておく変数です。例えば、buyポジションを3つ持っている状況であれば、3つ目のbuyポジションのlot数を意味します。current_sell_lotも同様です。
pre_buy_lot、pre_sell_lot
pre_buy_lotは、最新のbuyポジションの1つ前のlot数を記録しておく変数です。例えば、buyポジションを3つ持っている状況であれば、2つ目のbuyポジションのlot数を意味します。pre_sell_lotも同様です。
nanpin_lot
ナンピン注文を行う際に、変数を使って場合分けをするために、nanpin_lotという変数を用意しておきます。
ポジションの確認
ポジションを確認する処理の中で、lot数の確認も行うようにします。
機能追加前
ベースモデルでは、以下の記載でした。
buy_position=0;//buyポジション数の初期化
sell_position=0;//sellポジション数の初期化
current_buy_position=-1;//最新buyポジションの初期化
current_sell_position=-1;//最新sellポジションの初期化
for(cnt=0;cnt<OrdersTotal();cnt++)//ポジションの確認
{
if(OrderSelect(cnt,SELECT_BY_POS)==false)continue;
if(OrderMagicNumber()!=magic_number)continue;
if(OrderType()==OP_BUY)
{
current_buy_position=cnt;
buy_position+=1;
buy_profit=buy_profit+OrderProfit();
};//buyポジションの確認
if(OrderType()==OP_SELL)
{
current_sell_position=cnt;
sell_position+=1;
sell_profit=sell_profit+OrderProfit();
};//sellポジションの確認
}
機能追加後
これを、以下のように変更します。(「←今回追加」という行が、追加箇所です。)
buy_position=0;//buyポジション数の初期化
sell_position=0;//sellポジション数の初期化
current_buy_position=-1;//最新buyポジションの初期化
current_sell_position=-1;//最新sellポジションの初期化
current_buy_lot=0;//最新のbuyポジションのlot数の初期化 ←今回追加
current_sell_lot=0;//最新のsellポジションのlot数の初期化 ←今回追加
pre_buy_lot=0;//一つ前のbuyポジションのlot数の初期化 ←今回追加
pre_sell_lot=0;//一つ前のsellポジションのlot数の初期化 ←今回追加
for(cnt=0;cnt<OrdersTotal();cnt++)//ポジションの確認
{
if(OrderSelect(cnt,SELECT_BY_POS)==false)continue;
if(OrderMagicNumber()!=magic_number)continue;
if(OrderType()==OP_BUY)
{
current_buy_position=cnt;
buy_position+=1;
buy_profit=buy_profit+OrderProfit();
pre_buy_lot=current_buy_lot; //←今回追加
current_buy_lot=OrderLots(); //←今回追加
};//buyポジションの確認
if(OrderType()==OP_SELL)
{
current_sell_position=cnt;
sell_position+=1;
sell_profit=sell_profit+OrderProfit();
pre_sell_lot=current_sell_lot; //←今回追加
current_sell_lot=OrderLots(); //←今回追加
};//sellポジションの確認
}
追加箇所の中身を簡単に解説しておくと、全てのポジションを順番に確認していき、
buyポジションだったら、
- current_buy_lotを洗い替える前にpre_buy_lotにcurrent_buy_lot(1つ前のlot数)を記録する。
- current_buy_lotに最新ポジションのlot数を記録する。
というような処理を行なっています。
最後のbuyポジションまで確認した時の記録がpre_buy_lot、current_buy_lotに残って終わるという仕組みです。
追加エントリー(ナンピン)注文
続いて、ナンピン注文における機能追加です。
機能追加前
ベースモデルでは、以下の記載でした。
if(buy_position>0) //buyポジションを1つ以上持っている場合
{
OrderSelect(current_buy_position,SELECT_BY_POS); //最新のbuyポジションを選択
if(Ask<(OrderOpenPrice()-nanpin_range*Point)) //現在価格がナンピン幅に達しているか
{
ticket_number=OrderSend(
Symbol(), //通貨ペア
OP_BUY, //buy:OP_BUY, sell:OP_SELL
round(OrderLots()*1.5*100)/100, //ロット数
Ask, //注文価格
slippage, //スリッページ
0, //決済逆指値
0, //決済指値
"nanpin_buy", //注文コメント
magic_number, //マジックナンバー
0, //注文の有効期限
Blue //矢印の色
);
}
if(sell_position>0) //sellポジションを1つ以上持っている場合
{
OrderSelect(current_sell_position,SELECT_BY_POS); //最新のsellポジションを選択
if(Bid>(OrderOpenPrice()+nanpin_range*Point)) //現在価格がナンピン幅に達しているか
{
ticket_number=OrderSend(
Symbol(), //通貨ペア
OP_SELL, //buy:OP_BUY, sell:OP_SELL
round(OrderLots()*1.5*100)/100, //ロット数
Bid, //注文価格
slippage, //スリッページ
0, //決済逆指値
0, //決済指値
"nanpin_sell", //注文コメント
magic_number, //マジックナンバー
0, //注文の有効期限
Red //矢印の色
);
}
lotタイプの選択
ロット数については、OrderSend関数の中に以下のように直接書いていました。
round(OrderLots()*1.5*100)/100, //ロット数
これを、変数の定義で追加しておいたnanpin_lotを使って以下のように設定します。
//lotタイプの選択
if(lot_type==1){nanpin_lot = round(OrderLots()*1.5*100)/100;} //マーチン倍率 1.5倍
if(lot_type==2){nanpin_lot = round(OrderLots()*2*100)/100;} //マーチン倍率 2倍
if(lot_type==3){nanpin_lot = pre_buy_lot+current_buy_lot;} //ココモ法
後は、OrderSend関数の中のロット数の部分を、nanpin_lotに変えるだけです。
マーチン倍率 2倍については特に解説不要かと思うので、ココモ法について少し解説しておきます。
これは、1つ前のロット数に最新のロット数を加える形で次のロット数を決めます。
例えば、ロット数0.01のbuyポジションを1つ持っていれば、pre_buy_lotは0.00、current_buy_lotは0.01なので、nanpin_lotは0.01です。
以下同様に、
- pre_buy_lotが0.01、current_buy_lotが0.01なら、nanpin_lotは0.02
- pre_buy_lotが0.01、current_buy_lotが0.02なら、nanpin_lotは0.03
- pre_buy_lotが0.02、current_buy_lotが0.03なら、nanpin_lotは0.05
というロジックになります。
機能追加後
追加後は以下のようになります。
if(buy_position>0) //buyポジションを1つ以上持っている場合
{
OrderSelect(current_buy_position,SELECT_BY_POS); //最新のbuyポジションを選択
if(Ask<(OrderOpenPrice()-nanpin_range*Point)) //現在価格がナンピン幅に達しているか
{
//lotタイプの選択
if(lot_type==1){nanpin_lot = round(OrderLots()*1.5*100)/100;} //マーチン倍率 1.5倍
if(lot_type==2){nanpin_lot = round(OrderLots()*2*100)/100;} //マーチン倍率 2倍
if(lot_type==3){nanpin_lot = pre_buy_lot+current_buy_lot;} //ココモ法
ticket_number=OrderSend(
Symbol(), //通貨ペア
OP_BUY, //buy:OP_BUY, sell:OP_SELL
nanpin_lot, //ロット数
Ask, //注文価格
slippage, //スリッページ
0, //決済逆指値
0, //決済指値
"nanpin_buy", //注文コメント
magic_number, //マジックナンバー
0, //注文の有効期限
Blue //矢印の色
);
}
if(sell_position>0) //sellポジションを1つ以上持っている場合
{
OrderSelect(current_sell_position,SELECT_BY_POS); //最新のsellポジションを選択
if(Bid>(OrderOpenPrice()+nanpin_range*Point)) //現在価格がナンピン幅に達しているか
{
//lotタイプの選択
if(lot_type==1){nanpin_lot = round(OrderLots()*1.5*100)/100;} //マーチン倍率 1.5倍
if(lot_type==2){nanpin_lot = round(OrderLots()*2*100)/100;} //マーチン倍率 2倍
if(lot_type==3){nanpin_lot = pre_sell_lot+current_sell_lot;} //ココモ法
ticket_number=OrderSend(
Symbol(), //通貨ペア
OP_SELL, //buy:OP_BUY, sell:OP_SELL
nanpin_lot, //ロット数
Bid, //注文価格
slippage, //スリッページ
0, //決済逆指値
0, //決済指値
"nanpin_sell", //注文コメント
magic_number, //マジックナンバー
0, //注文の有効期限
Red //矢印の色
);
}
まとめ
以上で、ナンピンロット数の変更機能追加は完了です。
EAの動かし方、パラメーター設定等
実際に動かす方法、パラメーター設定等は以下の記事を参考にしてください。
その他のEA作成解説記事
取引時間制限、強制クローズ機能を追加
利確パターンの変更機能を追加
Pythonで作るFX自動売買ツール(bot)
PythonでFX自動売買ツール(bot)を作成する方法もご紹介しています。