基礎から学ぶシステムトレード
シストレブログ人気ランキング  

シストレ徹底攻略シストレマスターへの道ワールド・トレーディング・エッジ基礎から学ぶシステムトレードシストレニュースシストレツールシストレナビTOPへ

 

著書のご紹介

2012年07月10日(火)

売買システムの最適化(10) [MQL4]

売買システムの最適化を行う場合、変化させられるのはパラメータだけではありません。以前の記事で紹介した「複数のシステムの合成」を例に取ると、どのシステムを採用するかの組合せを最適化させることもできます。

例えば、6つのシステムがあり、それぞれが独立して売買を行うようになっているとします。

ここで、どのシステムのシグナルを採用するかを、下のような変数で判断します。値が1の場合採用し、0の場合採用しないとします。

extern int EnableSignal1 = 1;
extern int EnableSignal2 = 1;
extern int EnableSignal3 = 1;
extern int EnableSignal4 = 1;
extern int EnableSignal5 = 1;
extern int EnableSignal6 = 1;

これらの変数はexternを付けて宣言されているので、最適化のパラメータの入力として、それぞれの変数が0から1まで1刻みで変化するようにします。

画像(450x194)・拡大画像(667x288)

この場合、組合せの数は64通りとなります。

では、USD/JPYの日足データ2008年7月から2010年6月の2年分の範囲で最適化させてみましょう。

結果は、

EnableSignal1 = 0;
EnableSignal2 = 0;
EnableSignal3 = 1;
EnableSignal4 = 1;
EnableSignal5 = 1;
EnableSignal6 = 0;

の場合が最適となり、そのときの資産曲線はこのようになります。

画像(450x70)・拡大画像(800x125)

ちなみに同じパラメータで2010年7月から2012年6月までに適応させてみると、このようになります。

画像(450x70)・拡大画像(800x125)

この結果を見ると、最適化した期間の結果はいいのですが、別の期間での結果はそれほどいいとは言えませんね。カーブフィッティングになっている可能性が高いです。

今回はパラメータの組合せの数は64通りと少ないのですが、パラメータが一つ変わると、シグナルが全く変わることになるので、最適化した期間のみで最適になるパラメータを探索してしまったのかもしれません。

これまでシステムの最適化について色々とお話ししてきましたが、そろそろネタ切れです。次回からは違うテーマでお話しします。ではまた。

Posted at 17時57分 パーマリンク


2012年04月24日(火)

コピートレードのプログラミング(15) [MQL4]

これまで紹介してきたコピートレードのプログラムでは、コピー元のポジションのロット数がコピー先と全く同じになるようにトレードを行います。

ただ、場合によっては、コピー元の2倍のロット数でコピーしたい場合や、コピー元の半分のロット数にしたい場合などがあると思います。

今回は、コピー元のロット数に対して、コピー先のロット数を一定の倍率で変える場合についてプログラムしてみます。

まずは、その倍率を後から変更できるように

extern double Scaling = 1.0;

のように宣言しておきます。そして、このScalingという変数を

double remote_lots = FileReadNumber(handle) * Scaling;

のようにremote_lotsに掛けてあげます。

簡単な倍率の場合、これだけでもよいのですが、ロット数や倍率が小さい場合、ちょっと問題になることがあります。

例えば、コピー元のロット数が0.05で、倍率を0.7にした場合、コピー先のロット数は0.035となります。

オーダーできる最小ロット数やロット数の刻み幅は業者によって異なるので、ロット数の刻み幅が0.01の業者では、0.035ロットのオーダーを送信するとエラーになってしまいます。

なので、倍率をかけた後に、最小ロット数や刻み幅の条件にマッチするように調整する必要があります。

そこで、オーダーするロット数を調整する関数をAdjustLots()として次のように作成します。

double AdjustLots(double lots)
{
double abslots = MathAbs(lots);
double minlots = MarketInfo(Symbol(), MODE_MINLOT);
double lotstep = MarketInfo(Symbol(), MODE_LOTSTEP);
abslots = MathRound(abslots/lotstep)*lotstep;
if(abslots < minlots) abslots = 0;
if(lots < 0) abslots = -abslots;

return(abslots);
}

簡単に説明すると、まず、パラメータのlotsはプラスの場合とマイナスの場合があるので、abslotsにその絶対値を代入しておきます。

そして、MarketInfo()という関数で、お使いのMT4でオーダーできる最小ロット数をminlotsに、ロットの刻み幅をlotstepに求めます。

次に

abslots = MathRound(abslots/lotstep)*lotstep;

の式でロット数を調整するのですが、わかりやすいように具体的な数値を代入してみましょう。

例えば、abslots=0.042、lotstep=0.01の場合、abslots/lotstep=4.2となり、MathRound(abslots/lotstep)はそれを四捨五入するので4となります。それにlotstep=0.01をかけると、abslots= 0.04となり、刻み幅単位の値になります。

最後にabslotsがminlotsより小さければ0にし、元の符号をつけて返します。

この関数をtrade_lotsを求める式に追加します。

double trade_lots = AdjustLots(remote_lots - local_lots);

これで売買ロット数に端数が出ても、それを補正してオーダーが通るようになります。

全体のプログラムリストを以下に示します。

extern int MAGIC = 9999;   // マジックナンバー
extern int Slippage = 2; // スリッページ
extern double Scaling = 1.0; // ロットスケーリング

int start()
{
int handle = FileOpen("Position¥¥"+Symbol()+".txt", FILE_CSV|FILE_READ);
if(handle == -1) return(0);
double remote_lots = FileReadNumber(handle) * Scaling;
FileClose(handle);

double local_lots = OpenLots();

if(IsTradeAllowed() == false) return(1);
double slippage = Slippage;
if(Digits == 3 || Digits == 5) slippage *= 10;

// 決済オーダー
if(local_lots != 0 && (remote_lots == 0 || remote_lots*local_lots < 0))
{
for(int i=OrdersTotal()-1; i>=0; i--)
{
if(OrderSelect(i, SELECT_BY_POS) == false ) break;
if(OrderSymbol() != Symbol() || OrderMagicNumber() != MAGIC) continue;
if(OrderType() == OP_BUY || OrderType() == OP_SELL)
{
OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), slippage);
}
}
return(0);
}

// 部分決済オーダー
double trade_lots = AdjustLots(remote_lots - local_lots);
if(remote_lots*local_lots > 0 && local_lots*trade_lots < 0)
{
for(i=OrdersTotal()-1; i>=0; i--)
{
if(OrderSelect(i, SELECT_BY_POS) == false ) break;
if(OrderSymbol() != Symbol() || OrderMagicNumber() != MAGIC) continue;
if(OrderType() == OP_BUY || OrderType() == OP_SELL)
{
double close_lots = MathMin(OrderLots(), MathAbs(trade_lots));
OrderClose(OrderTicket(), close_lots, OrderClosePrice(), slippage);
return(0);
}
}
}

//売買オーダー
if(trade_lots > 0)
{
int ticket=OrderSend(Symbol(),OP_BUY,trade_lots,Ask,slippage,0,0,"",MAGIC);
}
if(trade_lots < 0)
{
ticket=OrderSend(Symbol(),OP_SELL,-trade_lots,Bid,slippage,0,0,"",MAGIC);
}
return(0);
}

// オープンロット数
double OpenLots()
{
double lots = 0.0;

for(int i=0; i<OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS) == false) break;
if(OrderSymbol() != Symbol() || OrderMagicNumber() != MAGIC) continue;

if(OrderType() == OP_BUY) lots += OrderLots();
if(OrderType() == OP_SELL) lots -= OrderLots();
}
return(lots);
}

// ロット数の補正
double AdjustLots(double lots)
{
double abslots = MathAbs(lots);
double minlots = MarketInfo(Symbol(), MODE_MINLOT);
double lotstep = MarketInfo(Symbol(), MODE_LOTSTEP);
abslots = MathRound(abslots/lotstep)*lotstep;
if(abslots < minlots) abslots = 0;
if(lots < 0) abslots = -abslots;

return(abslots);
}

ロット数補正の部分には、最大ロット数のチェックなども必要かもしれませんが、必要に応じて各自で追加してみてください。

以上でコピートレードのプログラミングの話は終わりにします。

次のネタは・・・これから考えます。

Posted at 10時14分 パーマリンク


2012年04月17日(火)

コピートレードのプログラミング(14) [MQL4]

コピートレードのプログラミングも佳境に入ってきました。今回は、コピー元のポジションを一度に決済するケースだけでなく、段階的に決済するケースにも対応させたEAを作ってみます。

まず、前回と同様に変数を定義しておきます。

remote_lots : コピー元のポジション
local_lots : コピー先のポジション
trade_lots = remote_lots - local_lots

オープンしているポジションの一部を決済する例を見てみましょう。

 remote_lots=0.1, local_lots=0.2, trade_lots=0.1-0.2=-0.1

の場合、コピー先の買いポジションの方が0.1ロット多いので、0.1ロットを決済する必要があります。また

 remote_lots=-0.1, local_lots=-0.2, trade_lots=-0.1-(-0.2)=0.1

の場合も、コピー先の売りポジションのうち、0.1ロットを決済する必要があります。

これを見ると、部分決済させるための条件は以下の二つの条件を同時に満たすときだとわかります。

1.remote_lotsとlocal_lotsの符号が同じ
2.local_lotsとtrade_lotsの符号が逆

二つの値の符号が同じか逆かというのは、前にも出てきたように、二つの値の積がプラスかマイナスかで判別できます。条件式は次のように書けます。

if(remote_lots*local_lots > 0 && local_lots*trade_lots < 0)

次に、部分決済するロット数について見てみます。

例えば、0.2ロットの買いポジションが二つある場合(合計0.4ロット)を考えてみましょう。

ここで、コピー元のポジションが0.3ロットになったとすると、一方のポジションのうち、0.1ロットだけを決済すればよいことになります。

またコピー元のポジションが0.1ロットになった場合は、一方のポジションすべてと、もう一方のポジションの0.1ロット分を部分決済する必要があります。

これらのケースを考慮すると、選択したポジションのロット数がtrade_lots以下であれば、すべて決済し、trade_lotsの方が小さければ、tarde_lotsの分だけ、部分決済すればよいことになります。

このような部分決済のコードは次のように書けます。

double close_lots = MathMin(OrderLots(), MathAbs(trade_lots));
OrderClose(OrderTicket(), close_lots, OrderClosePrice(), slippage);

close_lotsという変数に決済するロット数を算出しますが、条件文の代わりに、MathMin()という二つのパラメータの小さいほうを返す関数を使っています。

以上説明した部分決済のコードを追加した全体のプログラムは次のようになります。

extern int MAGIC = 9999;   // マジックナンバー
extern int Slippage = 2; // スリッページ

int start()
{
int handle = FileOpen("Position¥¥"+Symbol()+".txt", FILE_CSV|FILE_READ);
if(handle == -1) return(0);
double remote_lots = FileReadNumber(handle);
FileClose(handle);

double local_lots = OpenLots();

if(IsTradeAllowed() == false) return(1);
double slippage = Slippage;
if(Digits == 3 || Digits == 5) slippage *= 10;

// 決済オーダー
if(local_lots != 0 && (remote_lots == 0 || remote_lots*local_lots < 0))
{
for(int i=OrdersTotal()-1; i>=0; i--)
{
if(OrderSelect(i, SELECT_BY_POS) == false ) break;
if(OrderSymbol() != Symbol() || OrderMagicNumber() != MAGIC) continue;
if(OrderType() == OP_BUY || OrderType() == OP_SELL)
{
OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), slippage);
}
}
return(0);
}

// 部分決済オーダー
double trade_lots = remote_lots - local_lots;
if(remote_lots*local_lots > 0 && local_lots*trade_lots < 0)
{
for(i=OrdersTotal()-1; i>=0; i--)
{
if(OrderSelect(i, SELECT_BY_POS) == false ) break;
if(OrderSymbol() != Symbol() || OrderMagicNumber() != MAGIC) continue;
if(OrderType() == OP_BUY || OrderType() == OP_SELL)
{
double close_lots = MathMin(OrderLots(), MathAbs(trade_lots));
OrderClose(OrderTicket(), close_lots, OrderClosePrice(), slippage);
return(0);
}
}
}

//売買オーダー
if(trade_lots > 0)
{
int ticket=OrderSend(Symbol(),OP_BUY,trade_lots,Ask,slippage,0,0,"",MAGIC);
}
if(trade_lots < 0)
{
ticket=OrderSend(Symbol(),OP_SELL,-trade_lots,Bid,slippage,0,0,"",MAGIC);
}
return(0);
}

// オープンロット数
double OpenLots()
{
double lots = 0.0;

for(int i=0; i<OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS) == false) break;
if(OrderSymbol() != Symbol() || OrderMagicNumber() != MAGIC) continue;

if(OrderType() == OP_BUY) lots += OrderLots();
if(OrderType() == OP_SELL) lots -= OrderLots();
}
return(lots);
}

これで、コピー元のポジションの変化にだいたい対応することができるようになりました。

でもまだ続きがあります。

Posted at 12時00分 パーマリンク


過去の記事へ

ページのトップへ ページのトップへ

Sponsor AD

シストレナビモバイル

シストレナビモバイル
ケータイでバーコードを読み取りアクセス(詳細はこちら

プロフィール

豊嶋久道

2003年よりFX取引を始め、システムトレードの道へ。最近ではFXオプション取引も含めたトレーディングシステムの研究を行っている。システムトレードを基礎から正しく理解するための情報を発信する予定。

活動状況・Website

ToyolabFX
Toyolab FX-手ぶらで為替取引
FXトレーディング研究所。
FXメタトレーダー入門
FXメタトレーダー入門
最先端システムトレードソフト使いこなし術。
FXメタトレーダー実践プログラミング
FXメタトレーダー実践プログラミング
システム開発過程を段階的に学ぶ。

2017/10

1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        

PHOTO

ランダムウォークとランダムトレード(5)

ランダムウォークとランダムトレード(5)

カテゴリーリスト

最近の記事

スポンサードリンク

検索


上記の検索結果のRSS情報です RSS1.0

当サイトコメントについて

当コメントは情報提供のみを目的として作成されたものであり、投資に関してはご自身でご判断くださいますようお願い致します。また、当資料は著作物であり著作権法により保護されております。無断で全文または一部を転載することはできません。

RSS1.0

[Login]


powered by a-blog
Copyright (C) 2008 PhiConcept,Inc. All rights reserved.