プログラミングのタグを付けられた記事一覧

メール送信インジケータ

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

前回のインジケータを派手にするで、アラートウィンドウを開いたり、音を鳴らしたりしました。

今回は、メールを送信してみたいと思います。

ですが、メールの設定は結構めんどうなので、簡単にユーザを作れるYahooメールを例に設定を説明します。

とりあえず、Yahooメールと契約してください。

で、メール設定に「POPアクセスとメール転送」があります。

「ブラウザアクセスとPOPアクセス」にチェックを入れて、設定してください。

これで、Yahooメールの設定は終了です。

次は、メタトレーダーの設定です。

メニューのツール-オプションを開いてください。

「E-メール」タブで、

「有効にする」にチェックを入れます。

SMTPサーバー:「smtp.mail.yahoo.jpsmtp.mail.yahoo.co.jp:587」

SMTPログインID:「YahooのユーザID」

SMTPパスワード:「Yahooのパスワード」

発信元:「ユーザID@yahoo.co.jp」

送信先:「送信したいメールアドレス」

これを入力して、「Test」ボタンを押してください。

テストメールが送信されれば、設定OKです。

では、プログラムの方に行ってみましょう。

前回のソースを使います。

ここから、読み始めた人は、前回のインジケータを派手にするを見てくださいね。

では、DataSetを以下のように書き換えてください。

void DataSet(int i)

{

double dBBUp = iBands(NULL,0,Param1,2,0,PRICE_CLOSE,MODE_UPPER,i);

double dBBDown = iBands(NULL,0,Param1,2,0,PRICE_CLOSE,MODE_LOWER,i);

if(dBBUp < High[i])

{

ExtMapBuffer1[i]=dBBUp;

if(ExtMapBuffer1[i+1] == EMPTY_VALUE)

{

if(i == 0){

SendMail(”Test BB” , “BBUp Over:” + DoubleToStr(High[i],Digits));

PlaySound(”alert.wav”);

}

ExtMapBuffer1[i+1] = ExtMapBuffer2[i+1];

}

}

else

{

ExtMapBuffer2[i]=dBBUp;

if(ExtMapBuffer2[i+1] == EMPTY_VALUE)ExtMapBuffer2[i+1] = ExtMapBuffer1[i+1];

}

if(dBBDown > Low[i])

{

ExtMapBuffer3[i]=dBBDown;

if(ExtMapBuffer3[i+1] == EMPTY_VALUE)

{

if(i == 0){

SendMail(”Test BB” , “BBDown Over:” + DoubleToStr(Low[i],Digits));

PlaySound(”alert.wav”);

}

ExtMapBuffer3[i+1] = ExtMapBuffer4[i+1];

}

}

else

{

ExtMapBuffer4[i]=dBBDown;

if(ExtMapBuffer4[i+1] == EMPTY_VALUE)ExtMapBuffer4[i+1] = ExtMapBuffer3[i+1];

}

//   ExtMapBuffer5[i]=iMA(NULL,0,14,0,MODE_SMA,PRICE_WEIGHTED,i);

//   ExtMapBuffer6[i]=iMA(NULL,0,14,0,MODE_EMA,PRICE_WEIGHTED,i);

//   ExtMapBuffer7[i]=iMA(NULL,0,14,0,MODE_SMMA,PRICE_WEIGHTED,i);

//   ExtMapBuffer8[i]=iMA(NULL,0,14,0,MODE_LWMA,PRICE_WEIGHTED,i);

}

今回は、前回のアラートウィンドウの代わりにメール送信を行います。

SendMail(タイトル,本文);

を使います。

DoubleToStr(High[i],Digits)

で、High[i]の数字を文字型に変更しています。

DoubleToStr(double型の変数,有効小数点桁数)

Digitsは、現在の通貨ペアの小数点桁数を表します。

ということで、ボリンジャーバンドにタッチしたときの高値か安値をメールで送信するプログラムのできあがりです。

いままで、数回同じようなネタで行いましたが、結構簡単にいろいろなことができることが分かったと思います。

小難しいことを知らなくても意外と何とかなるでしょ!

では、また次回。

→この記事の続きを読む

タグ

インジケータを派手にする

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

前回のちょっと賢いボリンジャーバンドインジケータをちょっと派手にしたいと思います。

 

前回のソースをそのまま使うので、今回からお読みの方は、前回を参考にソースを作成してください。

 

で、どのように派手にするかというと、アラートウィンドウを開き、音を鳴らします。

リクエストもあったので、今回の例で説明します。

 

アラートウィンドウと音を鳴らすタイミングは、ボリンジャーバンドを抜けたときに行います。

 

では、DataSetを以下のように書き換えてください。

 

void DataSet(int i)

{

   double dBBUp = iBands(NULL,0,Param1,2,0,PRICE_CLOSE,MODE_UPPER,i);

   double dBBDown = iBands(NULL,0,Param1,2,0,PRICE_CLOSE,MODE_LOWER,i);

   if(dBBUp < High[i])

   {

      ExtMapBuffer1[i]=dBBUp;

      if(ExtMapBuffer1[i+1] == EMPTY_VALUE)

      {

         if(i == 0){

            Alert(”BBUp Over:”,High[i]);

            PlaySound(”alert.wav”);

         }

         ExtMapBuffer1[i+1] = ExtMapBuffer2[i+1];

      }

   }

   else

   {

      ExtMapBuffer2[i]=dBBUp;

      if(ExtMapBuffer2[i+1] == EMPTY_VALUE)ExtMapBuffer2[i+1] = ExtMapBuffer1[i+1];

   }

   if(dBBDown > Low[i])

   {

      ExtMapBuffer3[i]=dBBDown;

      if(ExtMapBuffer3[i+1] == EMPTY_VALUE)

      {

         if(i == 0){

            Alert(”BBDown Over:”,Low[i]);

            PlaySound(”alert.wav”);

         }

         ExtMapBuffer3[i+1] = ExtMapBuffer4[i+1];

      }

   }

   else

   {

      ExtMapBuffer4[i]=dBBDown;

      if(ExtMapBuffer4[i+1] == EMPTY_VALUE)ExtMapBuffer4[i+1] = ExtMapBuffer3[i+1];

   }

//   ExtMapBuffer5[i]=iMA(NULL,0,14,0,MODE_SMA,PRICE_WEIGHTED,i);

//   ExtMapBuffer6[i]=iMA(NULL,0,14,0,MODE_EMA,PRICE_WEIGHTED,i);

//   ExtMapBuffer7[i]=iMA(NULL,0,14,0,MODE_SMMA,PRICE_WEIGHTED,i);

//   ExtMapBuffer8[i]=iMA(NULL,0,14,0,MODE_LWMA,PRICE_WEIGHTED,i);

}

if(i == 0)でくくっているのは、過去のラインを描画するときにもメッセージや音が出てしまうためです。

新規にボリンジャーバンドを抜けたときだけ、処理を行います。

 

Alertは、アラートウィンドウを表示する関数で、引数はコメントと同じで「,」カンマ区切りで、文字や数値を連結できます。

PlaySoundは、音を出す命令で、引数にサウンドファイル名を指定します。

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

に入っているファイルを指定できます。

 

これで、好きなときに音を出したりできますね。

 

色々挑戦してみてください。

タグ

ちょっと賢いボリンジャーバンドインジケータ

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

前回に引き続き、「簡単インジケータ作成テンプレート」を使ったサンプルを作ってみます。

今回もボリンジャーバンドを利用します。

 

ボリンジャーバンドにタッチしたら、売ったり買ったりすることが結構あると思います。

でも、本当にタッチしているかどうか分かりにくいですよね。

なので、タッチしているときだけ色を変えるようなインジケータを作ってみます。

 

まだ、テンプレートをダウンロードしていない人は、「簡単インジケータ作成テンプレート」からダウンロードしてください。

 

indicator_temp.mq4をコピーして、適当な名前にしてください。

例として、BB_I.mq4とします。

このファイルは、

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

に入れてくださいね。

 

いつものようにメタトレーダーを起動して、メタエディターを開いてください。

そこで、先ほど作ったBB_I.mq4を開きます。

 

変更する場所は、一番下の関数

DataSetだけです。

 

以下のように修正してみてください。

 

void DataSet(int i)

{

   double dBBUp = iBands(NULL,0,Param1,2,0,PRICE_CLOSE,MODE_UPPER,i);

   double dBBDown = iBands(NULL,0,Param1,2,0,PRICE_CLOSE,MODE_LOWER,i);

   if(dBBUp < High[i])

   {

      ExtMapBuffer1[i]=dBBUp;

   }

   else

   {

      ExtMapBuffer2[i]=dBBUp;

   }

   if(dBBDown > Low[i])

   {

      ExtMapBuffer3[i]=dBBDown;

   }

   else

   {

      ExtMapBuffer4[i]=dBBDown;

   }

//   ExtMapBuffer5[i]=iMA(NULL,0,14,0,MODE_SMA,PRICE_WEIGHTED,i);

//   ExtMapBuffer6[i]=iMA(NULL,0,14,0,MODE_EMA,PRICE_WEIGHTED,i);

//   ExtMapBuffer7[i]=iMA(NULL,0,14,0,MODE_SMMA,PRICE_WEIGHTED,i);

//   ExtMapBuffer8[i]=iMA(NULL,0,14,0,MODE_LWMA,PRICE_WEIGHTED,i);

}

今回は、上下2色使うので、上側にExtMapBuffer1、ExtMapBuffer2

下側に、ExtMapBuffer3、ExtMapBuffer4を割り当てます。

ボリンジャーバンドの上側のラインより高値が高い場合に、ExtMapBuffer1に値をセット。

低い場合に、ExtMapBuffer2にセットします。

下側も同様にセットしています。

 

ボリンジャーバンドで利用する足の数を変えられるように、Param1を使いました。

 

コンパイルして、描画させたいグラフにドロップしてみてください。

Param1は0になっているので、21とか適当な値にしてください。

線の太さや色もパラメータで設定できますので、いじってみてくださいね。

 

表示させた結果、ちゃんと色が変わっているのが分かりましたか?

 

 

でも、なんか線が飛んでいませんか?

データを入れていないところは、デフォルトでEMPTY_VALUEという描画しない値が、入っています。

ちょうど、書き始めに値が入っていないため抜けているんですね。

 

というわけで、ちょっと気持ち悪いので、たりない情報を別のバッファからもらうように修正してみます。

 

void DataSet(int i)

{

   double dBBUp = iBands(NULL,0,Param1,2,0,PRICE_CLOSE,MODE_UPPER,i);

   double dBBDown = iBands(NULL,0,Param1,2,0,PRICE_CLOSE,MODE_LOWER,i);

   if(dBBUp < High[i])

   {

      ExtMapBuffer1[i]=dBBUp;

      if(ExtMapBuffer1[i+1] == EMPTY_VALUE)ExtMapBuffer1[i+1] = ExtMapBuffer2[i+1];

   }

   else

   {

      ExtMapBuffer2[i]=dBBUp;

      if(ExtMapBuffer2[i+1] == EMPTY_VALUE)ExtMapBuffer2[i+1] = ExtMapBuffer1[i+1];

   }

   if(dBBDown > Low[i])

   {

      ExtMapBuffer3[i]=dBBDown;

      if(ExtMapBuffer3[i+1] == EMPTY_VALUE)ExtMapBuffer3[i+1] = ExtMapBuffer4[i+1];

   }

   else

   {

      ExtMapBuffer4[i]=dBBDown;

      if(ExtMapBuffer4[i+1] == EMPTY_VALUE)ExtMapBuffer4[i+1] = ExtMapBuffer3[i+1];

   }

//   ExtMapBuffer5[i]=iMA(NULL,0,14,0,MODE_SMA,PRICE_WEIGHTED,i);

//   ExtMapBuffer6[i]=iMA(NULL,0,14,0,MODE_EMA,PRICE_WEIGHTED,i);

//   ExtMapBuffer7[i]=iMA(NULL,0,14,0,MODE_SMMA,PRICE_WEIGHTED,i);

//   ExtMapBuffer8[i]=iMA(NULL,0,14,0,MODE_LWMA,PRICE_WEIGHTED,i);

}

これで、試してみてください。

うまくいったでしょ。

ちなみにコンパイルするとパラメータの設定が初期化されてしまいます。

 

気になる人は、上の方の

#property indicator_color1 Red

#property indicator_color2 Blue

#property indicator_color3 Green

#property indicator_color4 Yellow

extern int Param1=0;

 

の値を変えてみてくださいね。

タグ

簡単インジケータ作成テンプレート

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

インジケータプログラムの楽しさを知ってもらうために、「簡単インジケータ作成テンプレート」を作成しました。

まず、ダウンロードしてください。

 

それでは、簡単に使い方を説明します。

 

indicator_temp.mq4

を作りたいインジケータ名に変更します。

 

今回は、サンプルでボリンジャーバンドを表示してみたいと思います。

ですので、ファイル名を「Bands_I.mq4」に変更してください。

 

リネームしたファイルを以下のフォルダーへコピーしてください。

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

 

では、メタトレーダーを起動して、メタエディターを起動してください。

ナビゲータウィンドウのFilesタブにindicatorsを開くと、ファイル一覧が表示されます。

ここに先ほどコピーした、「Bands_I.mq4」があるはずなので、ダブルクリックして開いてください。

 

下の方に、「DataSet」という関数があります。

このテンプレートでは、基本的にこの中だけをいじります。

 

では、以下のように書き換えてください。

 

void DataSet(int i)

{

   ExtMapBuffer1[i]=iBands(NULL,0,21,3,0,PRICE_CLOSE,MODE_UPPER,i);

   ExtMapBuffer2[i]=iBands(NULL,0,21,2,0,PRICE_CLOSE,MODE_UPPER,i);

   ExtMapBuffer3[i]=iBands(NULL,0,21,1,0,PRICE_CLOSE,MODE_UPPER,i);

   ExtMapBuffer4[i]=iMA(NULL,0,21,0,MODE_SMA,PRICE_CLOSE,i);

   ExtMapBuffer5[i]=iBands(NULL,0,21,1,0,PRICE_CLOSE,MODE_LOWER,i);

   ExtMapBuffer6[i]=iBands(NULL,0,21,2,0,PRICE_CLOSE,MODE_LOWER,i);

   ExtMapBuffer7[i]=iBands(NULL,0,21,3,0,PRICE_CLOSE,MODE_LOWER,i);

//   ExtMapBuffer8[i]=iMA(NULL,0,14,0,MODE_LWMA,PRICE_WEIGHTED,i);

}

 

ラインは、7本使うので最後の1行はコメントアウトしています。

ボリンジャーバンドの3θ、2θ、1θを上下1本ずつ、合計6本と中央に移動平均を引くので、合計7本です。

このように、メタトレーダー標準の関数の値を代入するだけで、お手軽にいろいろな線を引くことができるテンプレートとなっています。

標準では、メインウィンドウへ書きますので、現在のレートに近い値を代入しないと表示できません。

※範囲外になってしまうので。。。

もし、サブウィンドウに表示したいときは、
上の方にある
#property indicator_chart_window
//#property indicator_separate_window
//#property indicator_chart_window
#property indicator_separate_window

 

のようにコメントを変更してください。

ちなみに以下のように書き直すと、RSIが表示できます。

 

void DataSet(int i)
{
   ExtMapBuffer1[i]=iRSI(NULL,0,21,PRICE_CLOSE,i);
//   ExtMapBuffer2[i]=iMA(NULL,0,7,0,MODE_EMA,PRICE_WEIGHTED,i);
//   ExtMapBuffer3[i]=iMA(NULL,0,7,0,MODE_SMMA,PRICE_WEIGHTED,i);
//   ExtMapBuffer4[i]=iMA(NULL,0,7,0,MODE_LWMA,PRICE_WEIGHTED,i);
//   ExtMapBuffer5[i]=iMA(NULL,0,14,0,MODE_SMA,PRICE_WEIGHTED,i);
//   ExtMapBuffer6[i]=iMA(NULL,0,14,0,MODE_EMA,PRICE_WEIGHTED,i);
//   ExtMapBuffer7[i]=iMA(NULL,0,14,0,MODE_SMMA,PRICE_WEIGHTED,i);
//   ExtMapBuffer8[i]=iMA(NULL,0,14,0,MODE_LWMA,PRICE_WEIGHTED,i);
}

 

このように、比較的簡単にいろいろな指標を表示できます。

次回から、このテンプレートを使って遊んでみたいと思います。

タグ

プログラムが組める自分を想像する

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

FXや株でも何でもそうですが、過去のデータを参考に投資を行うと思います。

自分なりに、相場がこうなるといい感じになりそうだから買おう、とかルールを決めている人が多いと思います。

 

というか、ルールを決めないとほとんどギャンブルになっちゃうので、決めましょうね。

 

で、このルールを見つけるのが大変ですよね。

私も日々、見つけようと努力しています。

 

グラフなどをみて、この線を組み合わせるといいかもしれない!

と思ったら、過去にどうなっているか調べるわけです。

 

ここからが、プログラムを組める人と組めない人の差が開きます。

 

組めない人は、グラフとにらめっこして、ここでは増えた、ここではダメ。

とかすべて、見ていかなければなりません。

その上、パラメータをいじってみたら、もう一度同じことを繰り返す必要があります。

 

大変ですよね。

たぶん、ルールを見つける作業がいやになるのは、この辺ではないかと。。。

 

逆にプログラムを組める人は、最初にルールを元にしたプログラムを組みます。

後は、解析結果を待つだけです。

バックテストで、パラメータを変えながら最適な結果を見つける方法も説明しました。

 

1度組んでしまえば、解析まで自動でできます。

 

まあ、プログラムを組むのが面倒なんですがね。

 

プログラムを組める場合と組めない場合では、どちらが有利か説明するまでも無いと思います。

 

いままで、いろいろなサンプルで説明してきましたが、難しいと思う人も多いかと思います。

 

でも、行数を見てください。

 

100行ぐらいで、できているはずです。

たった100行ですよ。

 

これで、それなりのものができてしまうんです。

少し頑張ればできそうな気がしませんか?

 

メタトレーダーのプログラムは、ウィンドウズのプログラムを書こうと思うより、はるかに楽です。

 

よく考えてください。

やることは、値の比較だけ。

やっても何か特殊な計算をするぐらいですよね。

たくさんの指標を計算する関数がMT4には用意されているので、オリジナルで作ることは少ないと思います。

 

だから、指標の組み合わせと比較だけです。

 

全く目的が違うんです。

 

だから複雑なことをやらせないので、短いステップ数で完成することが多いんです。

 

いくつか、自分で組んでみると分かると思います。

まずは、まねから始めてみませんか?

 

覚えることは、

  1. 変数の宣言
  2. if文
  3. for文
  4. 標準で用意されている関数の呼び方

 

この4つをマスターすれば、あらかた組めますのでチャレンジしてみましょう。

4の標準で用意されている関数は、基本的に覚える必要はありません。

使いたいときに探して、目的のものがあれば使う。

無ければ計算で求めるだけです。

 

単純に考えましょう。

 

では、頑張ってください。

タグ

バックテストをしてみる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の特性で変わってくるでしょう。

 

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

 

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

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

タグ

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文にわたされるので、代入先の変数は必要ありません。

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

タグ