2009/02/19

Mizutori_EAの賞味期限


このEAの賞味期限を検討してみました。
対象バージョン:Mizutori20.1_Custom_EA(デフォルト)
使用データ:MQ(2006/1~2009/1)※問題はありますが検証用ということで。
添付グラフの説明:月別に取引回数と利益をまとめてみました。


参考資料:VIX指標(恐怖指数)http://chartpark.com/vix.html
参考資料(VIX指標5年)とグラフを見比べて頂くと類似しているような気がしませんか?
前々から気になっていたことですが、この指標を利用すればある程度このEAの賞味期限がわかってくると思っています。


例えば、VIX30以下になると、極端に取引回数が減少しそれに伴い利益も思うように上げることができなくなってきます。
それが、このEA(20.1)の賞味期限ではないでしょうか?
では、どうすればいいのでしょうか?
パラメータを変更して、取引回数を増やす?
たぶん得策ではありません。
私の考えでは、それを補うための新たなポジション取得条件の追加が必要だと考えています。
そのため、最近のバージョンは、新条件を追加したものが多数存在します。
また、新条件毎のPfの設定もできると面白いかもしれませんね。
もうひとつの賞味期限が、先に訪れるかもしれませんが・・・・・・
ご参考までに・・・・
追記
VIX指数が上限に近づくとどのような動きになるか?という質問がありましたので。
※この内容は、私の予測です。
まず、VIX指数とは、
将来の投資家心理を示す数値として利用されており、英語で「investor fear gauge」、日本語で「恐怖指数」という別名が付けられています。
VIX指数は、通常時10~20の範囲内動き、相場の先行きに不安が生じた時に数値が大きく上昇する特徴があります。 だそうです。 これから予測すると、 ①相場の先行きに不安があれば、投資家は、資金を引き揚げる。 ②引き揚げた資金を違う市場で運用する。(少なからず為替市場にも流れているはず。※市場の出来高がわかればある程度裏付けが取れるかもしれませんが、そのような立場にはいませんので確認が取れません。) ③市場での運用されている方のシステムは、ボラが大きくなれば利益が多くなるシステムだと聞いたことがあります。(順張のシステム?)資金量が増えれば行き過ぎた相場になる。これをウサギだとすると。 ④それを捕食するオオカミが増える。(荒れた相場では、乖離が有効とされているそうです。) ⑤VIXの数値が下がれば、資金が戻る。 ⑥ウサギの餌(資金)が減れば、ウサギも減りオオカミも減る。 ⑦オオカミが減れば、このEAの成績が下がる。 と予測しています。 つまり、このEAは、オオカミ的な要素のEAだと思っています。 ご参考までに・・・・・・

2009/02/13

Mizutori_EAのパラメーターの説明


いろいろなバージョンを作ってしまったので、今回は、25.4を基本に説明します。
共通事項
各パラメータに適用する価格は、極力初値(PRICE_OPEN)を使用しています。
理由は、バックテストした時の誤作動を防止するためです。
終値(PRICE_CLOSE)は、そのバーが確定するまで更新される値です。最新の決定された数値を得ようとすると、初値となります。
トレンドフィルター
double MaSS = iMA(NULL,0,25,0,MODE_EMA,PRICE_OPEN,0);
double MaSM = iMA(NULL,0,50,0,MODE_EMA,PRICE_OPEN,0);
double MaMS = iMA(NULL,0,100,0,MODE_EMA,PRICE_OPEN,0);
double MaMM = iMA(NULL,0,200,0,MODE_EMA,PRICE_OPEN,0);
double MaLM = iMA(NULL,0,300,0,MODE_EMA,PRICE_OPEN,0);
double MaLL = iMA(NULL,0,400,0,MODE_EMA,PRICE_OPEN,0);
上記6つの指数平滑平均線(EMA)を用いてトレンドの発生を監視しています。
各平均線がクロスすることなく、虹状態になった場合に『トレンドが発生した!』としています。
問題点
※『ダマシ』に弱いため、初期でフィルターが効かないことがある。
※『トレンドが発生していない(トレンドが消えた)部分を含んでしまう。』
メインエンジン
double Ma = iMA(NULL,0,MaPeriod,MaShift,MODE_SMA,PRICE_OPEN,0);
double Bands_Ma = iMA(NULL,0,10,0,MODE_SMA,PRICE_OPEN,0);
double Bands = Bands_Ma*(Percent/100);
double MaHi = Ma+Bands;
double MaLow = Ma-Bands;
上記の5つのコードでメインエンジンを構成している。
Maが軸となる移動平均線でデフォルト状態だと、期間5シフトをした期間10の単純移動平均線(SMA)。
Bands_Maは、バンドの巾を形成するための数値を得るための、期間0シフトの期間10の単純移動平均線(SMA)。
Bandsは、Bands_Maを用いて幅を形成しています。
MaHi・MaLowは、Maを軸にした上下の巾を形成したものです。
問題点
※Percentを固定しているため、極端な値動き、値動きが少ない時などの分別が付かない。また、USDJPYM5に特化した数値のため他の通貨ペアに対応しづらい。
サブエンジン
double MaHi_Tr = Ma*(1+Percent_Tr/100);
double MaLow_Tr = Ma*(1-Percent_Tr/100);
メインエンジンに同じ。ただし、使用目的に合わせるために、Percentをメインエンジンと異なる仕様にできるようにしてあります。
期間内の高値と安値の抽出
double HiLimt = High[iHighest(NULL,0,MODE_CLOSE,LimtPeriod,0)];
double LowLimt = Low[iLowest(NULL,0,MODE_CLOSE,LimtPeriod,0)];
LimtPeriod期間内の最も高い(低い)終値がついたバーの高値(安値)をHiLimt/LowLimtに格納
※敗戦処理及びXoxの計算に使用します。
期間内の最高値(最安値)を使用しない理由は、極度に長い髭(瞬間的に付けた値)を回避するためです。
問題点
現在のところ、特にありません。
その他のパラメーター
double RSI = iRSI(NULL,0,14,PRICE_CLOSE,0);
※終値を利用した、期間14のRSI(Relative Strength Index)(相対力指数)

double Dv = iStdDev(NULL,PERIOD_H4,Dv_Period,0,MODE_EMA,PRICE_CLOSE,0);
※終値を利用した、4時間足での標準偏差で、グローバルに値が動いた時のフィルターとして使用しています。
double ATR = iATR(NULL,0,ATRPeriod,0);
※突発的な値動きがあった時のフィルターとして使用しています。
問題点
以下のようなコードの指標のため、バックテストでフィルターが作用し、リアルでは効かない可能性があります。
※ATR (Average True Range)の内部コード
double high=High[i];
double low =Low[i];
double prevclose=Close[i+1];
TempBuffer[i]=MathMax(high,prevclose)-MathMin(low,prevclose)
【高値[0]と終値[1]の高い方から安値[0]と終値の低い方を引いた数値をTempBufferに格納
AtrBuffer[i]=iMAOnArray(TempBuffer,Bars,AtrPeriod,0,MODE_SMA,i);
【TempBufferの期間(デフォルトなら2)の平均がATRの数値となります。】
double stb = iMA(NULL,0,MaLimtPeriod,MaLimtShift,MODE_SMMA,PRICE_OPEN,0);
double st=(HiLimt-LowLimt)/(stb/100);⇒100×((HiLimt-LowLimt)/stb )と置き換えます。
※変動係数(本来は、標準偏差/平均値を意味します。)を求め変動係数が小さい時は、内部エネルギーが蓄積されたと判定し、トレードを制限するために使用します。
※stbは、期間(デフォルト500)の平滑移動平均線で、軸となる価格を抽出するために使用しています。
※stは、高低差を軸となる価格で割ったものを100倍した【変動係数】を格納するものです。
参考
下記の式が上記式に近似します。(添付Bora指標参照:青が下記の指標、白が上記指標です。)
double st=MathLog(HiLimt/LowLimt)*100;
※たぶん、logを使用した方が、本来の意味に近づくと思っています。(USDJPYでは、(HiLimt-LowLimt)/(stb/100)がフィットしています。)
ちなみに LogA=e^Aです。
まとめ
大きなトレンドを避けて、逆張りを行っていけばある程度の成績が可能になると思います。
また、追加もしくは削除しなければならない指標があることでしょう。
フィルターを締め付けると、ほとんど取引をしなくなり、緩めると大きな損益が発生しますので注意してください。
それでは・・・。

2009/02/11

成長曲線


オカミとウサギの話をした時のことを覚えていますか?
その中で、オオカミが0の場合ウサギの個体数は、どうなったでしょうか?
その時のグラフだと、無限に個体数を増やしていました。
自然界では、ありえませんね。
例えば、ウサギが食べる餌の量や、敷地に制限があり無限に個体数を増やすことは考えられません。
そこで、自然界をモデル化した公式があります。
代表的な物が、ゴンペルツ曲線とロジスティック曲線です。

ゴンペルツ関数
Y=a×b^EXP(-c×X)
※a=限界数:b=変数:-c=変数:EXP(J)=e(ネイピア数)のJ乗を意味する。
ロジスティック曲線
Y=a/(1+b×EXP(-c×X))
※a=限界数:b=変数:-c=変数:EXP(J)=e(ネイピア数)のJ乗を意味する。
添付したグラフは、系列1がゴンペルツ関数(a=100:b=0.1:c=1)で系列2がロジスティック関数(a=100:b=1:c=1)です。
2つの違い(特徴)は、ロジスティック関数が、変曲点に対し左右対称の曲線になるのに対し、ゴンペルツ関数は、非対称となることです。
成長曲線は、生物の個体数、プログラムのバグ累計数、販売累計台数などのモデルとして用いられているそうです。
ご参考までに。

2009/02/08

為替データ(USDJPY)

※ここに記載する内容は、私の思いこみで書かれています。
他の裏付けが取れている内容ではありません。

ヒストグラムを作成してみました。
ヒストグラムとは、データの分布状況を視覚的に認識するため作られたグラフのことです。

データの説明
ティック数1440以上とは、1分間に1回以上行われたデータつまり、1日分のデータがあると思われるデータのみ抽出しました。
データ区間のマイナス領域は、下げ日であった日、プラス領域は、上げ日であった日を表します。
また、横軸の数値が、区間(@0.1)を示し、縦軸がその区間に入るデータの数を示しています。
次のヒストグラムは、系列1が日足、系列2が4時間足、系列3が1時間足を示しています。
縦軸は、そのデータ区間が全体の区間に占める割合をパーセントで示しています。
これらのグラフからわかること
①ほぼ左右対称になっていることから、上げも下げも同様な変化量を持って変化していることが分かる。
②日足でみた場合、終値-初値の値が-2.5から2.5間に99.5% -2.0から2.0間で98.7% -1.5から1.5間で96.5% -1.0から1.0間88.9%のデータが入る。(グラフと元のデータより)
4時間足の場合、終値-初値の値が-1.0/1.0間99.1% -0.5/0.5間93.1% -0.3/0.3間82.3%
1時間足の場合、終値-初値の値が-0.3/0.3間96.0%
今回は、グローバルな視点でデータを検証してみたが、新しい発見ができませんでした。
今後、暇を見て、下記の検証をしてみようと思います。
ここからは、私の勝手な仮説です。
①『値は、動きたがっているようだ!』
値は、絶えず動きたがっていて、その理由を探している。何らかの要因で、その動きが止められた時その力は、蓄積される。
そして、その原因が、解決された時、蓄積された力は、放出される。
②『値動きは、指数関数的な動きをしそうだ!』
絶えず一定の割合で動くのではなく、成長曲線的な(ゴンペルツ曲線や、ロジスティック曲線)動きを見せることが多い。
③『どうも、値動きの激しい時間帯とそうでない時間帯がありそうだ』
たとえば、大きく分けて、アジアが中心となる時間帯とEUが中心となる時間帯とUSAが中心となる時間帯があり、その市場ごとで、値動きに違いがありそうだ。
また、1週間を通して急激なトレンドが発生した場合に週末に戻しが入ることが多そうだ。

2009/02/05

コピペでエラーが・・・


よく聞く話しですが、何を言っているのかわかりませんでした。
よく聞いてみると、サイトなどに書いてあるコードをそのままコピペしてEAに張り付けても動かないとのことです。
自分でやってみて納得しました。
原因は、全角スペースです。
コピペする際に、半角スペースで書かれているものが、全角スペースになるようです。
対策として、貼り付けた部分を、矢印キーでカーソル移動してみてください。問題の個所(全角スペース)の部分に【 @ 】が現れます。
それを削除すれば、対策終了です。
ご参考までに・・・

2009/02/04

Mizutori_EAの説明(カスタムユーザー向け①)


表示にバグがありましたので修正しました。
Mizutori_EAの内部で何を行っているか、順に説明していきます。
本職の方が見たら、ホントでそれでいいのか?と問いかけたくなるところがあると思います。気になりましたコメントください。)
では、初期化関数から見ていきます。
この初期化関数『init()』は、EAを作動した時に1度だけ作動する場所です。
 一度だけ処理すれば、解決する内容を記載します。
int init()
{①
マジックナンバーの取得
Mc1Number = MYMAGIC + MagicfromSymbol();
【MagicfromSymbol()関数で処理した数値にMYMAGICを加えMc1Number(大域変数)に格納する。】
Profitの確認
TPf = Take_Profit();
【Take_Profit()関数で処理した数値をTPf(大域変数)に格納する。】
return(0);
}①
後処理関数です。(省略可能)
int deinit()
{
return(0);
}

ティックが更新するたびにスタート関数『start()』が呼び出されます。
expert start function
int start() {
int Order = SIGNAL_NONE;
int pos1=0,pos2=0;
bool OderStop = false;
bool OderClose = false;
bool fbp = false;
bool fsp = false;
//double Profit =0;
int Now_Time = TimeCurrent();
【現在のサーバータイムをNow_Timeに格納】
//int NowDay = TimeDay(Now_Time);
int NowHour = TimeHour(Now_Time);
【現在のサーバータイムを時間軸(時)に変更し、NowHourに格納】
int NowMin = TimeMinute(Now_Time);
【現在のサーバータイムを時間軸(分)に変更して、NowMinに格納】
if(!IsTradeAllowed())return(0);
【もし取引が可能でなければ、start()関数終了】
オーダーの凍結
int NT,FrT,ExT;
if(Trade_Freeze)【もしTrade_Freezeが真(true)なら{から}までを実行する。】
{①
NT = (60*NowHour)+NowMin;
【(60*NowHour)+NowMin『現在のサーバータイム』をNTに格納】
 ※●分を×分に変換しています。
FrT = (60*Freeze_SH)+Freeze_SM;
【設定したオーダー凍結開始時間を分に変換してFrTに格納】
ExT = (60*Freeze_EH)+Freeze_EM;
【設定したオーダー凍結終了時間を分に変換してExTに格納】
if((FrT<ExT)&&(FrT<NT)&&(NT<ExT))OderStop = true;
【もし( )内の条件が真(true)ならOderStop に真を格納】
if((FrT>ExT)&&((FrT<NT)||(NT<ExT)))OderStop = true;
もし( )内の条件が真(true)ならOderStop に真を格納】
}①

週末制限 および制限
if(Weekend_Stop==true && DayOfWeek()== Stop_Day_Of_Week && NowHour>=Stop_Hours)OderStop = true;//週末のオーダーストップ
 【もし( )内の条件が真(true)ならOderStop に真を格納】DayOfWeek()は、現在のサーバータイムの曜日(日~土)を0から6の数値で表す関数です。
if(Weekend_Stop==true && DayOfWeek()>Stop_Day_Of_Week)OderStop = true;
 【もし( )内の条件が真(true)ならOderStop に真を格納】
if(Weekend_Close==true && DayOfWeek()==Close_Day_Of_Week && NowHour>=Close_Hours)OderClose = true;//週末のオーダー強制決済
 【もし( )内の条件が真(true)ならOderClose に真を格納】
if(Weekend_Close==true && DayOfWeek()>Close_Day_Of_Week)OderStop = true;
 【もし( )内の条件が真(true)ならOderStop に真を格納】

最後に決済したオーダーの抽出
1時間の間最後に決済されてから金額よりも悪い条件で取引することを防止するための仕様です。
 int ht = OrdersHistoryTotal( )-1;
 【過去のオーダー数 -1をhtに格納】
int ODT = 0;
for(int Z = ht ; Z>=0 ;Z--)
 【過去のオーダー数回{~}内を繰り返す。Zは、過去のオーダー数からの引き算】
 過去のオーダーは、古いものから新しいもの(最後に決済したもの)の順に並んでいます。一番古いもの・・・・・・・・・・一番新しいもの
{
if(OrderSelect(Z, SELECT_BY_POS, MODE_HISTORY) == true)//口座履歴の選択
  【もし過去のデータファイルからデータを抜き出せたら{~}内を処理する。】
{
if(OrderMagicNumber() != Mc1Number) continue;//マジックナンバー
【もしマジックナンバーが異なっていたらこの処理をスキップする。】
datetime HistoryLastTime = OrderCloseTime( ) ;//決済した時間
【決済した時間をHistoryLastTimeに格納する。】
double HistoryLastPrice = OrderOpenPrice( ) ;
 【注文した時の価格をHistoryLastPriceに格納】
ODT = ODT+1;
 【ODTに1を加える】
}
if(HistoryLastPrice>0)break;
 【HistoryLastPriceが0以上ならループから脱出する。】
 }
 //ポジション取得の許可
int now =TimeHour(Now_Time-HistoryLastTime) ;
 【現在の時間から最後に決済された時間を引いてnowに時間単位(時)で格納】
if((now>=1)||(ODT==0)||(Ask<=(HistoryLastPrice-(PipStep*Point))))fbp = true;
 【もし(最後に決済されてから1時間以上経過した)または(過去のオーダーがない)または(最後に決済した価格よりもASKが下回ったら)fbpに真を格納する。】
if((now>=1)||(ODT==0)||(Bid>=(HistoryLastPrice+(PipStep*Point))))fsp = true;//
 【もし(最後に決済されてから1時間以上経過した)または(過去のオーダーがない)または(最後に決済した価格よりもBidが上回ったら)fbpに真を格納する。】
if(!Sort_Order){fbp = true;fsp = true;}
 【もしSort_Orderが真でなければ{ }を処理】
オープンポジションの抽出
//ポジション数の確認およびラストオーダーの金額の抽出
ポジションは、古いオーダー・・・・新しいオーダーの順で格納されています。
double LastPrice = 0;
for(int i=0;i<OrdersTotal();i++)【注文分繰り返す】
{①
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true){② //注文ポジションの選択
【もしデータファイルからデータを抜き出せたら{~}内を処理する。】
if(OrderMagicNumber() != Mc1Number) continue;//マジックナンバー
【マジックナンバーが異なればスキップ】
if(OrderType()==OP_BUY)pos1++;
 【BUY注文があればpos1に1を追加する】
if(OrderType()==OP_SELL)pos2++;
 【SELL注文があればpos2に1を追加する】
LastPrice=OrderOpenPrice();
【約定金額をLastPriceに格納】
}②
}①
int posX = pos1+pos2;
if((posX==0)||(posX > NumPos))
【もし( )内の条件のどちらかが真から{①}内を繰り返す。】
{①
NumPos=posX;
if(NumPos>1 && UseStopLoss )Changes_Stoploss(Mc1Number,NumPos);
【もしナンピン回数(オーダー数の合計)が更新されたら、Changes_Stoploss()関数にMc1Number,NumPosの条件を与えて処理させる。】
}①
時間軸による変更(サーバータイム[GTM+0]
int NH = NowHour+ServerTime_GMT;
MaShift = MaShift_Custom(NH);
【MaShift_Custom( )にNHを与えて、その結果をMaShiftに格納】
Xox = Xox_Custom(NH);
【Xox_Custom( )にNHを与えて、その結果をXoxに格納】

今回はここまでにしておきます。

2009/02/03

Mizutori_EAの説明(カスタムユーザー向け④)


前回の続きです。
※ご指示頂きましたので修正しました。(2009/2/11)
ここからは、注文・決済・注文の変更になりますが、汎用性を高くするために多くの無駄な作業が含まれています
※不具合が見つかりました。不具合の場所を赤字で書いておきます。
◆ ポジションの決済 ◆
void ClosePositions(int Close_Type ,int Oder_Type ,int MagicNumber)
【void型の関数は、処理後の値がない関数(処理値を返さない関数です。)】
【ClosePositionsという名前の自作関数で、決済タイプ(0:1つだけ決済する、1;すべて決済する)決済する注文の種別、マジックナンバー、を受けて処理を行います。】
{【①まで有効】
int Error ;
RefreshRates();
【値を最新のものにする。】
for(int i=OrdersTotal()-1;i>=0;i--)【注文がある分繰り返す】
{【②まで有効】
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) break ; //注文ポジションの選択
【注文が、なければ処理を脱出する。】
if(OrderMagicNumber() != MagicNumber) continue; //マジックナンバー
【マジックナンバーが異なれば処理をスキップする。】
{ 【③まで有効】※不要かもしれません。
int type = OrderType();
【その注文のタイプを確認する。BUY or SELL】
if((type == OP_BUY && Oder_Type==SIGNAL_CLOSEBUY)||(type==OP_SELL && Oder_Type==SIGNAL_CLOSESELL))
【決済指示が来ている注文のタイプとその注文が同じタイプか確認し、同じタイプであるなら④内の処理を行う。】
{【④まで有効】
switch(type)【注文のタイプ別分儀】
{【⑤まで有効】
買ポジションに対する処理
case OP_BUY:【BUY注文の場合】
OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, MediumSeaGreen);
 【決済注文を行う(この注文のチケットナンバー、この注文のロット数、売値、スリペ、チャート上の決済位置の印の色)】
Error = GetLastError();
【上記処理のエラーをErrorに格納】
if(Error!=0){Print("Close Positions Error OrderTicket = ", OrderTicket());}else{【⑥まで有効】
【もし、処理時にエラーがあれば、エラー報告しなければ以下の処理を行う。】
if (SignalMail) SendMail("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Bid, Digits) + " Close Buy");
【メールを送るようになっていれば、(   )内の文面でメールを送る。】
if(SignalAlert)Alert("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Bid, Digits) + " Close Buy");
【アラート設定がなされていれば、(  )内の文面でアラートを発生させる。】
}⑥
if(Close_Type==0){return(0);}
【1つだけ決済する場合は、この関数を終了する。】
break;【swithchからの脱出】
売りポジションに対する処理
case OP_SELL: 【SLL注文の場合】
OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, DarkOrange);
【決済注文を行う(この注文のチケットナンバー、この注文のロット数、買値、スリペ、チャート上の決済位置の印の色)
Error = GetLastError();
【上記処理のエラーをErrorに格納】
if(Error!=0){Print("Close Positions Error OrderTicket = ", OrderTicket());}else{【⑦まで有効】
【もし、処理時にエラーがあれば、エラー報告しなければ以下の処理を行う。】
if (SignalMail) SendMail("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Ask, Digits) + " Close Sell");
【メールを送るようになっていれば、(   )内の文面でメールを送る。】
if(SignalAlert)Alert("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Ask, Digits) + " Close Sell");
【アラート設定がなされていれば、(  )内の文面でアラートを発生させる。】
}⑦
if(Close_Type==0){return(0);}
【1つだけ決済する場合は、この関数を終了する。】
break; 【swithchからの脱出】
}⑤
}④
}③
}②
}①
【処理値を返さなくていいので、return()がありません。】
◆ポジションの注文 ◆
void OrderPositions(int Order,int pok1,int pok2,int MagicNumber)
【戻り値のないOrderPositionsという名前の自作関数で、注文の種別、現在のBUY注文の数、現在のSELL注文数、マジックナンバーを受けて処理する。】
{ 【①まで有効】
//-------ロット数の計算
double StopLossLevel =0;
double Stp=0;
int pos = MathAbs(pok1 - pok2);
【現在の注文数をposに格納】
double Lots = 0;
if(Lot_Management){Lots=lotSizeCalc(pos);}else{Lots=Fixed_Lots;}
【ロット調整を行う場合は、lotSizeCalc自作関数を実行し、Lotsに格納。ロット調整をしない場合は、Fixed_Lots(指示値)をLotsに格納】
if(Order==SIGNAL_BUY)
【BUY注文の場合{②}内の処理を行う】
{【②まで有効】
Ticket=0;
if(AccountFreeMarginCheck(Symbol(),OP_BUY,Lots)<=0 || GetLastError()==134){【③まで有効】
【余剰証拠金を確認し、不足している場合{③}内を処理】
Print("We have no money. Free Margin = ", AccountFreeMargin());
【残高不足であることを記載する。】
return(0);【自作関数の終了】}
if (UseStopLoss){Stp= Ask-StopLoss*Point ;}else Stp = 0.0;
【損切り値を設定する場合、損切り値をstpに格納、設定しない場合は、stpに0を格納】
if (UseTakeProfit) TakeProfitLevel = Ask + (TPf*Point) ; else TakeProfitLevel = 0.0;
【利食い値を設定する場合、利食い値をTakeProfitLevelに格納、設定しない場合は、TakeProfitLevelに0を格納】
for(int bt=1;bt<= Order_Challenge ;bt++)【Order_Challenge(指示値)分{④}内を繰り返す】
{【④まで有効】
Ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage*Point, Stp, TakeProfitLevel, "Buy(#" + MagicNumber + ")", MagicNumber, 0, DodgerBlue);
現在の通貨ペア、BUY注文、注文数、買値、スリペ、損切り値、利食い値、履歴に(Buy(#マジックナンバー))と記入、マジックナンバー、現在の時間、チャート上に記載される色を指示し、注文する。また、注文状況をTicketに格納】
if(Ticket > 0) 【注文が処理されたら】{【⑤まで有効】
if (OrderSelect(Ticket, SELECT_BY_TICKET, MODE_TRADES)) {【⑥まで有効】
【注文がされているか再度確認するために、注文を確認し、注文がされていれば】
Print("BUY order opened : ", OrderOpenPrice());
【(BUY order open 約定金額)と履歴に残す】
if (SignalMail) SendMail("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Ask, Digits) + "@"+DoubleToStr(Lots,2)+"@ Open Buy");
【メール設定されていれば、( )内の文面でメールを送る。】
if(SignalAlert) Alert ("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Ask, Digits) + "@"+DoubleToStr(Lots,2)+"@ Open Buy");
【アラート設定されていれば、( )内の文面でアラートを表示する。】
break ;【処理を抜け出す。】
⑥} else { ⇒ ⑥}⑤}else{⑦ 【不具合発見です。既設(赤部)だと1度目の注文確認で真、2回目の確認で偽にならないと、エラー報告が発生しないようになっています。変更が必要です。】
【変更内容は、1度目の確認が偽ならエラー処理をする。というものです。】
【2回目の確認は、本来注文の呼び出しがメインのため、エラー処理なしとしてみました。】
if(SignalAlert) Alert("Error opening BUY order : ", GetLastError());
【アラート設定がなされている場合、( )内を表示(エラー報告)】
Sleep(5000);//5秒間停止
【5秒間停止】
}【上記不具合のため、削除】
}⑦
}④
}③
if(Order==SIGNAL_SELL)
【SELL注文の場合{⑦}内の処理を行う】
{【⑦まで有効】
Ticket=0;
if(AccountFreeMarginCheck(Symbol(),OP_SELL,Lots)<=0 || GetLastError()==134){【⑧まで有効】
【余剰証拠金を確認し、不足している場合{⑧}内を処理】
Print("We have no money. Free Margin = ", AccountFreeMargin());
【残高不足であることを記載する。】
return(0); 【自作関数の終了】}⑧
if (UseStopLoss){Stp= Bid+StopLoss*Point ;}else Stp = 0.0;
【損切り値を設定する場合、損切り値をstpに格納、設定しない場合は、stpに0を格納】
if (UseTakeProfit) TakeProfitLevel = Bid - (TPf*Point) ; else TakeProfitLevel = 0.0;
【利食い値を設定する場合、利食い値をTakeProfitLevelに格納、設定しない場合は、TakeProfitLevelに0を格納】
for(int sc = 1;sc<= Order_Challenge ;sc++)【Order_Challenge(指示値)分{⑨}内を繰り返す】
{【⑨まで有効】
Ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage*Point, Stp, TakeProfitLevel, "Sell(#" + MagicNumber + ")", MagicNumber, 0, DeepPink);
【現在の通貨ペア、SELL注文、注文数、売値、スリペ、損切り値、利食い値、履歴に(Buy(#マジックナンバー))と記入、マジックナンバー、現在の時間、チャート上に記載される色を指示し、注文する。また、注文状況をTicketに格納】
if(Ticket > 0) 【注文が処理されたら】{【⑩まで有効】
if (OrderSelect(Ticket, SELECT_BY_TICKET, MODE_TRADES)) {【⑪まで有効】
【注文がされているか再度確認するために、注文を確認し、注文がされていれば】
Print("SELL order opened : ", OrderOpenPrice());
【(SELL order open 約定金額)と履歴に残す】
if (SignalMail) SendMail("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Bid, Digits) + "@"+Lots+"@ Open Sell");
【メール設定されていれば、( )内の文面でメールを送る。】
if(SignalAlert) Alert ("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Bid, Digits) + "@"+Lots+"@ Open Sell");
【アラート設定されていれば、( )内の文面でアラートを表示する。】
break ; 【return(0);の方がいいかもしれません。】
⑪} else { ⇒ ⑪}⑩}else{⑫ 【不具合発見です。既設(赤部)だと1度目の注文確認で真、2回目の確認で偽にならないと、エラー報告が発生しないようになっています。変更が必要です。】

【変更内容は、1度目の確認が偽ならエラー処理をする。というものです。】
【2回目の確認は、本来注文の呼び出しがメインのため、エラー処理なしとしてみました。】

if(SignalAlert) Alert("Error opening SELL order : ", GetLastError());
【アラート設定がなされている場合、( )内を表示(エラー報告)】
Sleep(5000);//5秒間停止
【5秒間停止】
} 【上記不具合のため、削除】
}⑫
}⑨
}②
}①
◆ Stoplossの変更(注文の変更)◆
void Changes_Stoploss(int MagicNumber,int pos)
【戻り値のないChanges_Stoplossという自作関数で、マジックナンバー、ナンピン回数を受けて処理します。】
{【①まで有効】
int Error ;
int Total = OrdersTotal()-1;
【注文数の合計をTotalに格納】
int K = Total-pos+1;※不具合処理のため削除
for(int i=Total;i>=K;i--) ⇒ for(int i=0;i> Total;i++) ※不具合発生のため変更
{【②まで有効】
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) break ; //注文ポジションの選択
【注文の呼び出し、及び 注文がなければ、処理を脱出】
if(OrderMagicNumber() != MagicNumber) continue; //マジックナンバー
【マジックナンバーが異なればスキップ】
{ 【③まで有効】※たぶん要らない
int type = OrderType();
【その注文タイプをtypeに格納】
switch(type)【注文タイプの分儀】
{【④まで有効】
//買ポジションに対する処理
case OP_BUY:【BUY注文の場合】
OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss( )-Point*StopStep,OrderTakeProfit(),0,Yellow);
【注文の変更(注文番号、注文値、損切り値、利食い値、時刻、黄色)で変更を行う】
Error = GetLastError();
【エラーをErrorに格納】
if(Error!=0){Print("Changes Stoploss Error OrderTicket = ", OrderTicket());}
【エラーがあるなら、履歴に残す】
break;【処理を脱出】
//売りポジションに対する処理
case OP_SELL:【SELL注文の場合】
OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss( )+Point*StopStep,OrderTakeProfit(),0,Yellow);
【注文の変更(注文番号、注文値、損切り値、利食い値、時刻、黄色)で変更を行う】
Error = GetLastError();
【エラーをErrorに格納】
if(Error!=0){Print("Changes Stoploss Error OrderTicket = ", OrderTicket());}
【エラーがあるなら、履歴に残す】
break; 【SELL注文の場合】
}④
}③
}②
} ①
//+---------------------------------------------------------------- END ------------------------------------------------------------------+

2009/02/01

相手を確認することが重要です。


※この内容は、EAの販売を推奨するものではありません。
よく、EAの販売を否定する人たちが、上げる理由があります。
『販売すれば(多数の人が使えば)同時にそのポジションでオーダーが入り、値が崩れる。そうすれば、EAの性能が落ち、利益があげられなくなる。それよりも、本当に有能なEAなら自分でコツコツ稼いだ方がいい。だから有能なEAなんて売っていない。』

この考えは本当でしょうか?
『私は、必ずしもそうとは思いません。』(EAの販売を推奨するものではありません。)
まず、私たちは、誰と取引をしているか?という点です。
FX取引は、【株の取引】と違い、FX業者との【相対取引】です。
【相対取引】とは、市場を介さずに売買当事者間で売買する方法。
つまり、相手は、FX業者であって、市場ではない。
では、買値と売値は、FX業者が勝手に作っているのか?という点です。
それは違います。インターバンク市場の値を参考にFX業者が作っています。(金融庁の目があり、あまり酷い事はできないはずです。)
【1分足の範囲内で、細かく値を操作し1~2pips滑らせることは可能でしょうね。】
だから、FX業者によって多少値にばらつきがあるものの、ほぼ似たような値になっているのです。
『だったら、大量のオーダーを出しても、値が変わらない?(動かない?)』
決してそうだとは言えません。なぜならFX業者もインターバンク市場とのカバー取引をしているはずだからです。
『はず』と書いたのは、インターバンク市場との取引の際にもやはり手数料がかかります。USDJPYで1銭から2銭だそうです。
【相対取引】でスプレッド1の場合、カバー取引を行えば行うほど、手数料分の負債が生じます。
カバー取引数=BUY数-ASK数(買い注文と売り注文の差がカバー取引数になるはずです。)

例えば、1つのEAで値を動かすことができる条件とは、
『独裁的なEAが存在し、かつFX業者がカバー取引をした場合、しかも、通常時の安定した市場では、USDJPYを10pips動かすのに1000万通貨のオーダーが必要だと言われていますので、カバー取引量が、その程度になった場合に値を動かすことができる。』
と思われます。

単独EAでは、考えづらいと思いませんか?
私の考えは、否定的です。
それよりも、単独でカバー取引しなければならないEAは、FX業者から何らかの処置が課せられるでしょうね。
だから、有能なEAは、売っていない!という結論になるかもしれませんが・・・
賞味期限(一様に成績が良い期間)があるのであれば、販売して利益を得た方が得策かもしれません。(EAの販売を推奨する意味合いではありません。)

いろいろ書きましたが、『自分が誰と取引をしているのか?』その相手を知ることも重要な要因であることは、間違いありません。