2009年05月の記事一覧

ダウンロードセンター開設

4XP => メタトレーダー対応、固定スプレッド、最小1000通貨
50種類以上の通貨ペア、各種CFD(金、株など)対応

まだまだ、記事数も多くない「めたぷろ」ですが、せっかくプログラムを説明していてもダウンロードできるファイルがどこにあるか分かりにくくなってきました。

 

ということで、「MT4 めたぷろ ダウンロードセンター」を開設しました。

めたぷろで、紹介したコードやサンプルファイルをダウンロードするためのサイトです。

記事がない分、探しやすくなると思います。

 

ちょこっと作ってみたインジケータやEAがあるので、めたぷろで紹介しないものも順次公開予定です。

たまにのぞいてみてください。

タグ

フォワードテストをしてみる

4XP => メタトレーダー対応、固定スプレッド、最小1000通貨
50種類以上の通貨ペア、各種CFD(金、株など)対応

前回、前々回とバックテストをやってみました。

では、今回はフォワードテストです。

 

バックテストは、過去の履歴データを元にテストを行いました。

フォワードテストは、未来です。

 

未来は、わからないじゃないか!!

って、いう人もいると思いますがその通りです。

 

分からないので、実際に走らせてみるのがフォワードテストです。

でも、テストというだけあって、実弾口座では行いません。

 

デモ口座でのテストということになります。

 

簡単に言うと、デモ口座でEAを走らせることをフォワードテストといいます。

 

なぜ、こんなことをやるかというと、

過去のデータは、ある程度は信用おけますが、通信の問題やPCの負荷など色々問題がありそうな気がしませんか?

それに、ちゃんと思ったように動くかやってみないと分かりませんよね。

 

ということで、実際のEAの動きのチェック。

パラメータ調整は、大丈夫だったか。

といったことを確かめることがフォワードテストの意味するところです。

 

資金に余裕がある人で、自分の作ったEAに自信があれば、このフェーズは飛ばしてもかまいませんが、

少なくても2週間ぐらいはやった方がいいでしょう。

 

このフェーズで、もしダメでもデモですから懐は痛みません。

納得がいくまで、バックテスト、フォワードテストを繰り返してください。

 

ここで焦るとしっぺ返しが大きいので。。。

 

ということで、バックテスト、フォワードテストはしっかりと!

という話でした。

タグ

バックテストをしてみる2

4XP => メタトレーダー対応、固定スプレッド、最小1000通貨
50種類以上の通貨ペア、各種CFD(金、株など)対応

前回、EAを作ってみるでつくったEA(自動売買)、MA_EAをバックテストしてみました。

結果は、あまりよくありませんでしたね。

 

でも、EAを作ったときにパラメータをいくつか外出しにしたと思います。

覚えていますか?

 

もしかしたら、このパラメータをいじるといい感じの結果が出そうな予感がしませんか?

思わなくてもしたことにしてください。

話が進まないので。。。

 

で、パラメータのパターンをテストしていけばいいだけです。

たとえば、1つのパラメータで5パターンするとします。

 

1つで5パターン。

  楽勝!!

2つで25パターン。

  ちょっといやになってきますね。

3つで、125パターン。

  やる気でないですね。

4つで、625パターン。

  もう無理です。

 

やっぱり無理でした。。。

っていうことになりそうですが、メタトレーダーには、便利な機能があります。

 

スタート、ステップ、ストップの値をパターン分析したいパラメータにセットすると、すべての組み合わせを行ってくれる機能があるんです。

テスターに「Optimization」というチェックがあったのに気がつきませんでしたか?

このチェックが、パターン分析を行うチェックなんです。

 

では、チェックを入れてスタート!

と行く前に、

先ほどの説明のスタート、ステップ、ストップを設定して、どのパラメータを変更して解析させるかを指定する必要があります。

 

では、「Expert properties」ボタンを押して、プロパティウィンドウを開いてください。

次に、「パラメータの入力」タブを押してください。

では、設定していきます。

 

BuyLots:変更しません。

LossEntry:変更しません。

残りは、すべてチェックします。

MaPerirod:スタート(7)、ステップ(7)、ストップ(35)

TakeMa:スタート(5)、ステップ(5)、ストップ(25)

LossMa:スタート(5)、ステップ(5)、ストップ(20)

TakeEntry:スタート(25)、ステップ(5)、ストップ(50)

 

では、早速スタートを押してみましょう!

 

以下のタグに利益が出ているものだけ表示されます。

Optimization Results:損益やトレード回数、ドローダウンと利用したパラメータ

Optimization Graph:損益のグラフ

 

すべての解析が終了するまで、待ってください。

 

Optimization Resultsの損益をクリックしたください。

利益の多い順や少ない順にソートされます。

他の項目も同様です。

 

利益の多い順に並べます。

 

では、一番利益の多い行をダブルクリックしてください。

セッティングタブに戻ると思います。

「Optimization」のチェックが外れていることを確認してください。

 

先ほどのダブルクリックで、「Expert properties」のパラメータに選択行のパラメータが自動的にセットされました。

 

では、このパラメータでバックテストをとしてみましょう。

スタートボタンを押してください。

 

今度は、利益が出ましたね。

100pipsぐらいは増えたと思います。

 

サンプル用に適当に作ったEAとしては、まずますですかね。

 

バックテストは、こんな感じで行います。

 

ちなみに、一番利益が上がっているからいいパラメータではありません。

ドローダウンが大きく損失も大きいかもしれません。

 

たまたまその月はよかったと思いますが、未来もよいとは限りません。

また、テストの期間などもどのぐらいがいいのか?というのもEAの特性で変わってくるでしょう。

 

この辺はやってみないと分かりませんね。

 

とりあえず、これというパラメータが決まったあとは、フォワードテストというのを行います。

次回は、フォワードテストについて書きたいと思います。

タグ

バックテストしてみる

4XP => メタトレーダー対応、固定スプレッド、最小1000通貨
50種類以上の通貨ペア、各種CFD(金、株など)対応

今回は、バックテストのやり方を説明します。

前回のEAを作ってみるで作ったMA_EAを利用して、バックテストしてみたいと思います。

 

バックテストは、デモ環境でしか行えません。

もしかしたら、本番環境でも行えるかもしれませんが、121証券ではレートの履歴データをデモ環境でしか取得できないためです。

まず、本番環境の人はデモ環境に切り替えてください。

ナビゲーターの口座に、本番とデモ用の口座があるはずです。

デモ口座をダブルクリックして、切り替えてください。

デモ口座がない場合や期限切れの場合は、メニューのファイル-デモ口座の申請で申し込んでください。

 

デモ口座は、有効期限(121証券は2週間)がありますが、何度でも申請できるので期限が切れたら申請しましょう。

121証券の場合

申請するとき、口座タイプを選択できます。

forex-jpyを選択してください。

日本のサーバになるので、実際の口座に近くなります。

121証券の場合、時間が日本時間になっているので、時間による操作を考えるとこちらの口座を選択しておいた方がいいでしょう。

 

では、バックテストに必要な履歴データを取得します。

メニューのツール-History CenterかF2キーを押してください。

 

ヒストリー・センター

ヒストリー・センター

今回のテストは、USDJPYで行おうと思うので、通貨ペアのタブを開き、USDJPYを選択してください。

次にDownloadボタンを押して、出てきたウィンドウはOKを押してください。

履歴のダウンロードが始まります。

ダウンロードには、時間がかかるので気長に待ちましょう。

また、テストするときは最新の情報が必要なので、毎回ダウンロードするようにしてください。

 

ダウンロードが終了したら、閉じるボタンを押してください。

 

次にテスターを開きます。

メニューの表示-Strategy Testerを選択してください。

 

テスター

テスター

 Expert Advisor:MA_EA

通貨ペア:USDJPY

モデル:Every tick

期間:M5

期間を全期間で行うと時間がかかるので、4月にしたいと思います。

「日時と時間を使用」にチェックを入れます。

送信者:2009.04.01

宛先:2009.04.30

を指定します。

これで、5分足の4月1日から30日までの試験を行えます。

 

次に、いくらでテストをするか設定します。

Expert propertiesをクリックしてください。

ma_ea_param

日本円では、テストができないのでUSD、500ドルを指定します。

121証券の最低入金額が5万円なので近いところで500ドルとします。

 

パラメータの入力タブでは、EAのパラメータを設定できますが、今回はそのまま利用します。

では、試験をやってみましょう。

スタートボタンを押してください。

tester2

こんな感じで終了です。

ちなみに、「Visual mode」にチェックを入れてスタートすると描画しながらトレードの様子を見ることができます。

描画スピードは、バーを操作することで変更できます。

 

Graphタブを押すと以下のようなグラフになっていると思います。

testergraph

ダメでしたね。

減っています。

 

ちなみに、結果タブではトレードの詳細、レポートタブでは売買レポートが表示されます。

 

こんな感じで、バックテストを実行します。

 

次回は、パラメータを変更しながらバックテストを行い、最適なパラメータを見つける方法を説明します。

タグ

EAを作ってみる2

4XP => メタトレーダー対応、固定スプレッド、最小1000通貨
50種類以上の通貨ペア、各種CFD(金、株など)対応

前回のEAを作ってみるで説明不足のところを説明します。

 

まず、スリップについてです。

成行でオーダーするときに、メタトレーダーではAskかBidの金額を指定してオーダーします。

しかし、為替は動いていますので、この金額からずれていることがあります。

ですが、注文をなるべく成功させたいと考えたときに、ズレの許容値を指定することができます。

これが、スリップです。

 

スリップは、オーダーするときもクローズするときも指定可能です。

OrderSend(Symbol(),OP_SELL,BuyLots,Bid,3,Bid+LossEntry*Point,Bid-TakeEntry*Point,”MA_EA Sell”,MagicNo,0,Blue);

OrderClose(OrderTicket(),OrderLots(),Bid,3,Green);

の3がスリップの値になります。

 

ですから、Bidから+-3pipsのズレまで、許可するということになります。

このズレ以上の場合は、オーダーされないことになります。

 

クローズの方が失敗するのがいやな人は、多めを指定した方がいいでしょう。

 

次は、自分でオーダーした注文かどうかを判断する方法です。

前回は、マジックナンバーというのを利用しました。

他にもオーダーしたときにもらえるチケットナンバー、コメントなどをキーに探すことが可能です。

ただし、チケット番号は再起動したときに分からなくなってしまうので、マジックナンバーを利用するのがいいでしょう。

※グローバル変数を使うことで、2週間覚えておく方法もあります。

 

なぜ、このようなことを行うかというと、利用中の口座のオーダーはすべて見ることができてしまうからです。

別の通貨ペアでも、別のEAでも、手動オーダーでもなんでも見ることができます。

ですから、自分のEAが注文したものかどうかを判断する必要があるんです。

 

初めてのEAなので、こうしたことをやならくてもよかったのですが、今後EAを作る場合、こうした仕組みで作ることになると思い、初めからちゃんとした機能を持たせました。

そのため、少し難しくなっています。

 

ちなみに、すべて見えることの応用ですが、たとえば週末にすべてのオーダーをクローズするEAなんていうのも作ることができます。

週末の持ち越しはしたくない!って方で、販売されているEAを利用している方は、こうしたEAを作れると便利かもしれませんね。

タグ

EAを作ってみる

4XP => メタトレーダー対応、固定スプレッド、最小1000通貨
50種類以上の通貨ペア、各種CFD(金、株など)対応

今回は、EA(自動売買)のプログラムを作ってみたいと思います。 今回は、単純移動平均のラインをブレイクしたときに順張りするEAを作成します。  

単純移動平均をブレイクしたときに、成行でオーダーし、テイク(利益確定)ポイントとロスカットポイントを指定します。

これは、通信できなかったときの保険で、実際の利益確定やロスカットはEAが値を確認して行います。  

 

注意事項ですが、ここで作成したプログラムを実運用で利用してもかまいませんが、利益を保証するものではありません。

ご自分の判断で、利用してください。

損害等は、一切保証しません。

 

では、プログラムの作成を行いましょう。  

MetaEditorを開き、Expert Advisor Wizardを開きます。  

Expert Advisor作成

Expert Advisor作成

Expert Advisorを選択し、次へを押します。

 

EAの名前を決める

EAの名前を決める

NAMEに「MA_EA」と入力します。

パラメータを指定できますが、今回はコード上で指定しますので、そのまま完了を押してください。

スケルトンが作成されます。

 

前半の設定を行います。

 

//オーダーするときのロット数をパラメータとして指定します。

//0.1ロットが1万通貨となります。

extern double BuyLots=0.1;

//単純移動平均のサンプリングする足の数をパラメータとして指定します。

extern int MAPeriod=21;

//EAが利益確定するポイント数をパラメータとして指定します。

extern int TakeMA=20;

//EAがロスカットするポイント数をパラメータとして指定します。

extern int LossMA=10;

//オーダー時に保険として設定する利益確定ポイントを指定します。

extern int TakeEntry=25;

//オーダー時に保険として設定するロスカットポイントを指定します。

extern int LossEntry=25;

 

//オーダー番号を格納する変数を設定します。

int ticket=0;

//このEAのオーダーを判断するための番号を設定します。

int MagicNo=1;

 

今回は、初期処理と終了処理ではなにも行いません。

実行処理を指定します。

 

int start()

  {

//ポジションを持っているか判断するフラグを設定します。

//0がポジションなし、1がポジションを持っていることにします。

    int KeepPosition=0;

//現在持っているオーダー数を取得します。

    int total=OrdersTotal();

    int i;

//現在持っているオーダーの中からこのEAがポジションを持ったオーダーを探します。

    for(i=0;i < total;i++){

//オーダーを選択します。

        if(OrderSelect(i, SELECT_BY_POS)==true)

        {

//オーダーの通貨ペアが同じで、このEAが指定したマジックNoが同じものを探します。

            if(Symbol() == OrderSymbol() && OrderMagicNumber() == MagicNo)

            {

//このEAがオーダーしたものが見つかったときはオーダーを持っていることにします。

                KeepPosition = 1;

//チケット番号をセットします。

                ticket=OrderTicket();

//ループを抜けます。

                break;

            }

        }

    }

 

//現在から過去の単純移動平均を5本分取得します。

    double Ma0=iMA(NULL,0,MAPeriod,0,MODE_SMA,PRICE_CLOSE,0);

    double Ma1=iMA(NULL,0,MAPeriod,0,MODE_SMA,PRICE_CLOSE,1);

    double Ma2=iMA(NULL,0,MAPeriod,0,MODE_SMA,PRICE_CLOSE,2);

    double Ma3=iMA(NULL,0,MAPeriod,0,MODE_SMA,PRICE_CLOSE,3);

    double Ma4=iMA(NULL,0,MAPeriod,0,MODE_SMA,PRICE_CLOSE,4);

 

//ポジションを持っている場合、クローズするか確認します。

    if(KeepPosition == 1)

    {

//オーダーから何本足を描画したかを求めます。

//オーダーから最小値、最大値を求めるために利用します。

        int ChkAshi = (OrderOpenTime()-TimeCurrent())/(Period()*60);

//売りポジションの場合

        if(OrderType() == OP_SELL)

        {

//オーダーしてから、TakeMAの2倍の値を出して、TakeMAまで戻ってきたときにクローズします。

//利益確定は、戻ってきたときとオーダー時に設定したポイントの2つが利益確定ポイントです。

            if(OrderOpenPrice()-TakeMA*Point >= Ask && OrderOpenPrice()-TakeMA*2*Point >= Low[iLowest(NULL,0,MODE_LOW,0,ChkAshi)])

            {

                OrderClose(OrderTicket(),OrderLots(),Ask,3,Green);

            }

//LossMAで指定したポイントを割ってしまったときにロスカットします。

            if(OrderOpenPrice()+LossMA*Point <= Ask)

            {

                OrderClose(OrderTicket(),OrderLots(),Ask,3,Green);

            }

        }

//買いポジションの場合

//売りポジションと同じことを行います。

//符号の向きが逆なのとAskではなくBidを利用しているところが違います。

        else if(OrderType() == OP_BUY)

        {

            if(OrderOpenPrice()+TakeMA*Point <= Bid && OrderOpenPrice()+TakeMA*2*Point <= High[iHighest(NULL,0,MODE_HIGH,0,ChkAshi)])

            {

                OrderClose(OrderTicket(),OrderLots(),Bid,3,Green);

            }

            if(OrderOpenPrice()-LossMA*Point >= Bid)

            {

                OrderClose(OrderTicket(),OrderLots(),Bid,3,Green);

            }

        }

    }

 

//ポジションを持っていない場合、ポジションを持つかどうか確認します。

    else if(KeepPosition == 0)

    {

//下降トレンドの場合

        if(Ma4 > Ma3 && Ma3 > Ma2 && Ma2 > Ma1 && Ma1 > Ma0)

        {

//Ma4、Ma3、Ma2のクローズが大きくて、Ma1と現在値(Bid)が小さい場合売りポジションを持ちます。

            if(Ma4 < Close[4] && Ma3 < Close[3] && Ma2 < Close[2] && Ma1 > Close[1] && Ma0 > Bid)

            {

                ticket=OrderSend(Symbol(),OP_SELL,BuyLots,Bid,3,Bid+LossEntry*Point,Bid-TakeEntry*Point,”MA_EA Sell”,MagicNo,0,Blue);

                if(ticket==0) Print(”Error opening SellChk order : “,GetLastError());

            }

        }

//上昇トレンドの場合

        else if(Ma4 < Ma3 && Ma3 < Ma2 && Ma2 < Ma1 && Ma1 < Ma0)

        {

//Ma4、Ma3、Ma2のクローズが小さくて、Ma1と現在値(Bid)が小さい場合買いポジションを持ちます。

            if(Ma4 > Close[4] && Ma3 > Close[3] && Ma2 > Close[2] && Ma1 < Close[1] && Ma0 < Ask)

            {

                ticket=OrderSend(Symbol(),OP_BUY,BuyLots,Ask,3,Ask-LossEntry*Point,Ask+TakeEntry*Point,”MA_EA Buy”,MagicNo,0,Red);

                if(ticket==0) Print(”Error opening BuyChk order : “,GetLastError());

            }

        } 

    }

 

   return(0);

  }

 

OrderSelectで、選択しているオーダーはOrder???関数で値を取得することができます。

Low[iLowest(NULL,0,MODE_LOW,0,ChkAshi)、High[iHighest(NULL,0,MODE_HIGH,0,ChkAshi)]は、オーダーしてからの最安値、最高値を求めています。

OrderSendは売買注文を行う関数で、成行、IFD、OCOなどのオーダーを組み合わせて注文することができます。

今回の例では、成行+OCO注文を行っています。

また、ticketが0の場合は注文失敗で、GetLastErrorを利用してエラー番号を取得しています。

Printは、操作履歴に結果を出力する関数です。

操作を残したいときに利用すると便利です。

次は、バックテストのやり方を説明したいと思います。

 

 

今回のプログラムは、以下からダウンロードできます。

ここから、ダウンロード

 

EA(自動売買)は、

インストールパス\MetaTrader\experts

に入れてください。

 

タグ

トレンドラインを書いてみる3

4XP => メタトレーダー対応、固定スプレッド、最小1000通貨
50種類以上の通貨ペア、各種CFD(金、株など)対応

さて、前回と前々回で、トレンドラインを書くプログラムの基本とプログラムを書くときに気をつけたほうがいいことを書きました。

 

今回は、トレンドラインの総仕上げとして、ループ回数を最小にして、好きな本数のトレンドラインを書くインジケータを作成します。

少々、難易度が上がりますが、がんばってついてきてください。

 

トレンドラインを書いてみるを参考にインジケータのスケルトンを作成してください。

前回のソースにそのまま上書きでもかまいません。

 

まず、前半の定義部分です。

#property indicator_chart_window
extern int nPeriod=9;
extern int Limit=350;
extern int nLine=3;

nLineを追加しました。

これは、トレンドラインの数です。

デフォルトでは、3本ずつ書きます。

 

初期化部分です。

int init()
{
    int i;
    for(i=0;i<nLine;i++)
    {
        ObjectCreate(”Trend DN-”+i,OBJ_TREND,0,0,0,0,0);
        ObjectSet(”Trend DN-”+i,OBJPROP_COLOR,Maroon);
        ObjectSet(”Trend DN-”+i,OBJPROP_WIDTH,3);

        ObjectCreate(”Trend UP-”+i,OBJ_TREND,0,0,0,0,0);
        ObjectSet(”Trend UP-”+i,OBJPROP_COLOR,Green);
        ObjectSet(”Trend UP-”+i,OBJPROP_WIDTH,3);
    }

   return(0);
}

 

オブジェクトの作成ですが、前回と違って指定した数だけ作る必要があるため、ループをまわして指定した数のトレンドラインを書くためのオブジェクトを作成します。

名前が、「Trend UP-0″」など固定でしたが、数にあわせて名前を変更したいので、「Trend UP-”+i」としてループの値を名前に追加するように変更しました。

また、線が細くて見にくかったので、今回は少し太く描画させて見ます。

ObjectSet(”Trend DN-”+i,OBJPROP_WIDTH,3);

の部分で、線の幅をデフォルトの1ポイントから3ポイントに広げます。

 

次は、終了処理です。

int deinit()
{
    int i;
    for(i=0;i<nLine;i++)
    {
        ObjectDelete(”Trend UP-”+i);
        ObjectDelete(”Trend DN-”+i);
    }
   return(0);
}

初期処理と同じく、指定された数分だけ削除するようにループしています。

 

次は、本題のメイン処理です。

int start()
{

//今回は、線の数が分からないので、配列を使います。
//まず、空の配列を用意します。
//固定で指定する場合は、double r[10];の様に数字を指定します。
    double r[];
    int rt[];
    double s[];
    int st[];

//配列に必要な入れ物を指定した数だけ用意します。
//はじめと終わりの入れ物が必要なので、実際の線の数より1つ多い数を指定します。
    ArrayResize(r,nLine+1);
    ArrayResize(rt,nLine+1);
    ArrayResize(s,nLine+1);
    ArrayResize(st,nLine+1);

    int nCurBar;
    int ChkRLine=0;
    int ChkSLine=0;

    if(Bars<Limit) Limit=Bars-nPeriod;

//前回とは逆に最新のものから指定本数までループをまわします。
    for(nCurBar=0; nCurBar<Limit; nCurBar++)
    {

//一番低い谷を見つけます。
        if(Low[nCurBar+(nPeriod-1)/2] == Low[iLowest(NULL,0,MODE_LOW,nPeriod,nCurBar)])
        {
//値が1つだけでは線を引けないので、配列に代入だけします。
            if(ChkSLine==0)
            {
                s[ChkSLine]=Low[nCurBar+(nPeriod-1)/2];
                st[ChkSLine]=nCurBar+(nPeriod-1)/2;
                ChkSLine++;
            }
//2本目の値で、1つ目の値より小さい場合描画します。
            else if(s[ChkSLine-1] < Low[nCurBar+(nPeriod-1)/2] && ChkSLine <= nLine)
            {
//値の代入を行い
                s[ChkSLine]=Low[nCurBar+(nPeriod-1)/2];
                st[ChkSLine]=nCurBar+(nPeriod-1)/2;
//描画させます。
                ObjectMove(”Trend DN-”+(ChkSLine-1),1,Time[st[ChkSLine-1]],s[ChkSLine-1]);
                ObjectMove(”Trend DN-”+(ChkSLine-1),0,Time[st[ChkSLine]],s[ChkSLine]);
//ラインを1つ進めます。
                ChkSLine++;
            }
//もし、1つ前より小さい値が見つかったときに値を入れ替えます。
            else if(s[ChkSLine-1] > Low[nCurBar+(nPeriod-1)/2] && ChkSLine <= nLine)
            {
                s[ChkSLine-1]=Low[nCurBar+(nPeriod-1)/2];
                st[ChkSLine-1]=nCurBar+(nPeriod-1)/2;
            }
        }


//谷と同様に山を見つけます。
        if(High[nCurBar+(nPeriod-1)/2] == High[iHighest(NULL,0,MODE_HIGH,nPeriod,nCurBar)])
        {
            if(ChkRLine==0)
            {
                r[ChkRLine]=High[nCurBar+(nPeriod-1)/2];
                rt[ChkRLine]=nCurBar+(nPeriod-1)/2;
                ChkRLine++;
            }
            else if(r[ChkRLine-1] > High[nCurBar+(nPeriod-1)/2] && ChkRLine <= nLine)
            {
                r[ChkRLine]=High[nCurBar+(nPeriod-1)/2];
                rt[ChkRLine]=nCurBar+(nPeriod-1)/2;
                ObjectMove(”Trend UP-”+(ChkRLine-1),1,Time[rt[ChkRLine-1]],r[ChkRLine-1]);
                ObjectMove(”Trend UP-”+(ChkRLine-1),0,Time[rt[ChkRLine]],r[ChkRLine]);
                ChkRLine++;
            }
            else if(r[ChkRLine-1] < High[nCurBar+(nPeriod-1)/2] && ChkRLine <= nLine)
            {
                r[ChkRLine-1]=High[nCurBar+(nPeriod-1)/2];
                rt[ChkRLine-1]=nCurBar+(nPeriod-1)/2;
            }
        }

//上昇・下降ともに指定本数見つかった場合、ループを抜けます。
        if(ChkSLine > nLine && ChkRLine > nLine)break;
    }

   return(0);
}

 

メイン処理は、ループの中に納まっていて、必要な本数が見つかった後、breakで抜けいていることが分かると思います。

必要な数だけ、ループをまわすようにして負荷を抑えています。

値は、配列に格納しています。

本当は、配列に代入しなくても描画だけなら可能です。

ですが、今後の拡張のために値を残しておくようにしました。

値を残しておくことで、いろいろ拡張できると思います。

 

値の格納も1つ目の変数への格納と、条件を満たした場合に次の配列へ格納すること、一度格納した配列より大きい・小さい値の場合入れ替える処理を追加してあります。

 

少々複雑になりましたが、コンパクトにまとまっていると思います。

 

今回のプログラムは、以下からダウンロードできます。

 

インジケータは、

インストールパス\MetaTrader\experts\indicators

に入れてください。

タグ

かるく文法(省略記号編)

4XP => メタトレーダー対応、固定スプレッド、最小1000通貨
50種類以上の通貨ペア、各種CFD(金、株など)対応

質問があったので、MQL4で有効な四則演算での省略記号の説明を追加します。

 

省略記号編

 

符号(+-)を2回繰り返すことで、1足したり、引いたりすることと同じになります。

i++;

→ i=i+1;

i–;

→ i=i-1;

 

複数の足し引きをしたい場合

i+=2;

→ i=1+2;

i-=3;

→ i=i-3;

 

このように同じ数の足し引きには、便利ですので覚えておくといいでしょう。

また、サンプルでもよく使われますので、意味を覚えておいてください。

 

ちなみに

i-;

では、通常の引き算としてあつかわれるので、iから右辺のものを引こうとしますが右辺が無いためエラーになります。

また、

i-1;

では、計算結果が左辺に出力されますが、結果を受け取ることができません。

 

省略記号以外は、

代入先の変数=計算式;

と記述してください。

 

if文などは、()内の変数を利用するため、代入先の変数を用意する必要はありません。

if(a==1)

は、

a==1の計算結果が、trueかfalseになり、その値が引数としてif文にわたされるので、代入先の変数は必要ありません。

関数の説明は、後ほど行います。

タグ

トレンドラインを書いてみる2

4XP => メタトレーダー対応、固定スプレッド、最小1000通貨
50種類以上の通貨ペア、各種CFD(金、株など)対応

前回紹介した、トレンドラインを書いてみるはご覧になりましたか?

MT4でも手動で書くことができますが、やっぱり自動が楽ですよね。

 

でも、ちゃんと動くと思いますが、実はあまりいいプログラムではありません。

ちゃんと動く=いいプログラム

ではないということです。

 

では、何が悪いか。。。

 

ソースを見た時点で、だめだめジャン!!

って思った人は、プロかセミプロレベルの人ですね。

 

では、どこがダメなんでしょうか?

 

まず、for文でループを回している部分がありますよね。

ここが、ダメです。

for文じゃなくて、while文を使うってわけじゃありません。

基本的にループをまわすには、どちらを使ってもかまいません。

使いやすい方を使ってください。

 

では、ダメな部分。

調査する足の最大数からカウントダウンしてますよね。

古い方から新しい方へ調査しています。

 

別に古い方から新しい方へループをまわすことが悪いんじゃないんですが、今回はダメです。

実際に動かすと、トレンドラインを引く山や谷を見つけるのに、新しい方から数十本の足ですんでいますよね。

ということは、無駄なループをたくさん回しているということになります。

 

ループは、結構PCに負担なんです。

為替は、生き物ですから1秒でも無駄にしたくありませんよね。

だから、無駄を省く必要があります。

 

ですから、正解は新しい方から古い方にループを回して、必要な山や谷を見つけたらループを抜けるように組めばいいんです。

「break」という命令で、ループを抜けることができます。

 

もう一つあります。

ループの中で余分な変数に代入して、ループを抜けた後に上昇・下降か判断している部分があります。

ループ内で、判断すれば無駄が省けますよね。

 

プログラムは、動くことも大事ですがこうした無駄を省くように心がけると結果的に高速に動いたり、見やすいソースになります。

ぜひ、自分で組むときは心がけてください。

 

次は、もう一度トレンドラインを引くインジケーターを作ります。

上記で説明した、ダメな部分の修正ともう一つ。

表示してみると分かりますが、最新の1本だけだとトレードに使えません。

少なくても3本ぐらいないと、トレードの参考にならないはずです。

ですから、1本のトレンドラインから3本に増やします。

 

次回をお楽しみに!

タグ

トレンドラインを書いてみる

4XP => メタトレーダー対応、固定スプレッド、最小1000通貨
50種類以上の通貨ペア、各種CFD(金、株など)対応

前回は、インジケーターを作ってみるで足に対応したバッファに代入することで、メタトレーダーの機能を使いグラフを自動的に描画方法を試してみました。

今回は、オブジェクトという機能を使い好きな場所に線や文字などを描画する方法を試してみます。

 

で、単純に線を書いてもおもしろくないのでトレンドラインを書いてみたいと思います。

 

トレンドとは、上下に動きながら移動している為替も平均してみると上昇していたり、下降しているときがあります。

こうした状態をトレンド相場と呼びます。

平均した線が横ばいの場合は、レンジ相場と呼びます。

 

為替は、上昇トレンド、下降トレンド、レンジ相場の3種類のどれかの状態になっています。

 

このトレンドを表す線をトレンドラインと呼びます。

上昇トレンドラインは、上下に動いている山の高値と高値を結んだ線。

下降トレンドラインは、谷の安値と安値を結んだ線のことをいいます。

 

このトレンドラインをインジケーターの機能を使って、描画したいと思います。

 

インジケーターを作ってみるを参考にスケルトンを作ります。

Nameを「TrendLine」。

その他は、何も入力しません。

 

まずは、TrendLineのスケルトンを作成してください。

 

まず、前半の宣言部分を作成します。

//メインウィンドウに描画します。

#property indicator_chart_window

//山と谷を見つける幅をパラメータとして指定します。

extern int nPeriod=9;

//先頭から何本まで山、谷を見つけるかパラメータとして指定します。

extern int Limit=350;

 

次は、初期化処理です。

int init()

{

//下降トレンドライン0番目のオブジェクトを作ります。

    ObjectCreate(”Trend DN-0″,OBJ_TREND,0,0,0,0,0);

//下降トレンドライン0番目のオブジェクトの色を指定します。

    ObjectSet(”Trend DN-0″,OBJPROP_COLOR,Maroon);

 

//上昇トレンド0番目のラインオブジェクトを作成します。

    ObjectCreate(”Trend UP-0″,OBJ_TREND,0,0,0,0,0);

    ObjectSet(”Trend UP-0″,OBJPROP_COLOR,Green);

 

   return(0);

}

上昇、下降用のトレンドラインを引くためのオブジェクトを用意しました。

次は、終了処理です。

int deinit()
{
//オブジェクトを削除します。
    ObjectDelete(”Trend UP-0″);
    ObjectDelete(”Trend DN-0″);
   return(0);
}

 

インジケータを削除したときに、オブジェクトが残ってしまいます。

そのために、インジケータ終了時に自分が作ったオブジェクトを削除する処理を追加します。

次は、トレンドラインを描画するための山、谷を見つけラインを引く処理です。

 

int start()
{

//山、谷の値と足番号を格納する変数と描画する値を格納する変数を宣言します。

    double r1,r2,r3,r_1,r_2;
    int rt1,rt2,rt3,rt_1,rt_2;
    double s1,s2,s3,s_1,s_2;
    int st1,st2,st3,st_1,st_2;
    int nCurBar=0;

 

//表示されている足の数が、Limitより小さい場合、nPeriod引いた値をセットします。
//検査用の領域を確保するためです。
    if(Bars<Limit) Limit=Bars-nPeriod;

 

//検査する足を古い方からセットしていきます。
    for(nCurBar=Limit; nCurBar>0; nCurBar–)
    {

 

//検査する足の数の中心の安値が、検査する足の範囲で最小の安値の場合
//最新の安値をs1に代入します。
//S1を代入する前に過去の安値をS3、S2と古い変数へスライドさせて格納します。
        if(Low[nCurBar+(nPeriod-1)/2] == Low[iLowest(NULL,0,MODE_LOW,nPeriod,nCurBar)])
        {
            s3=s2; s2=s1; s1=Low[nCurBar+(nPeriod-1)/2];
            st3=st2; st2=st1; st1=nCurBar+(nPeriod-1)/2;
        }

 

//安値と同様に高値を変数へ代入します。
        if(High[nCurBar+(nPeriod-1)/2] == High[iHighest(NULL,0,MODE_HIGH,nPeriod,nCurBar)])
        {
            r3=r2; r2=r1; r1=High[nCurBar+(nPeriod-1)/2];
            rt3=rt2; rt2=rt1; rt1=nCurBar+(nPeriod-1)/2;
        }
    }

 

//2つの安値を比べたときに最新の安値が下降している場合のみ描画します。
//そのために各谷の安値を比較して、下降している隣接している谷を見つけます。
//もし、存在しない場合はデフォルトでEMPTY_VALUEがセットされているため、描画されません。
    if(s1 < s2){
        s_1=s1;
        s_2=s2;
        st_1=st1;
        st_2=st2;
    }
    else if(s2 < s3){
        s_1=s2;
        s_2=s3;
        st_1=st2;
        st_2=st3;
    }

 

//描画開始位置と次の点を設定します。
    ObjectMove(”Trend DN-0″,1,Time[st_1],s_1);
    ObjectMove(”Trend DN-0″,0,Time[st_2],s_2);
//上昇トレンドラインも下降トレンドラインと同様にセットします。
    if(r1 > r2){
        r_1=r1;
        r_2=r2;
        rt_1=rt1;
        rt_2=rt2;
    }
    else if(r2 > r3){
        r_1=r2;
        r_2=r3;
        rt_1=rt2;
        rt_2=rt3;
    }
    ObjectMove(”Trend UP-0″,1,Time[rt_1],r_1);
    ObjectMove(”Trend UP-0″,0,Time[rt_2],r_2);
   return(0);
}

 

これで、終了です。

コンパイルして、インジケータを表示させてみてください。

以下のようにトレンドラインが表示されれば成功です。

TrendLineインジケーター

TrendLineインジケーター

ちょっとは、らしいものができたのではないでしょうか?

少しずつレベルをアップしていきますね。

 

今回のプログラムは、以下からダウンロードできます。

ここから、ダウンロード

 

インジケータは、

インストールパス\MetaTrader\experts\indicators

に入れてください。

 

→この記事の続きを読む

タグ