■自動売買プログラム(EA)ひな形(フォーマット)
私は、MetaTrader(MT4)で自動売買プログラム(EA)を作成する際には、以下に記載するようなプログラム構成で作成しています。
MT4で自動売買を開始する(EAを動かす)と定期的に実行されるOnTick()関数内から、以下の処理を行う関数を呼び出す形としています。
- トレンド判定(上昇、下降トレンドか、トレンドなしかの判定)
- エントリー判定(エントリー条件を満たしていればポジション保有)
- クローズ判定(クローズ条件を満たしている場合はポジション解放)
それぞれの関数内で、トレード手法(ロジック)を実現する処理を実装(コーディング)します。
プログラム経験者(C言語とか)、もしくは、ちょっとプログラムの勉強をしたら、使っているMT4で用意されている関数の仕様をHelpやネット検索で調べれば、比較的簡単に分かるレベルなのではないかと思います。
(1)プログラム例
私が使用しているプログラムは以下のような感じです。
ちょっと補足。
OnInit()は、EAが最初に起動された時に呼ばれる関数です。OnTick()は、トレード中、定期的(ティックが動くたびに動作:EAの作りにもよりますが毎秒くらいに呼び出されると思って頂いて良いかと)に実行される関数です。この中で、チャートの状態を確認、注文条件を満たしたら、新規注文、決済注文を行う、といったことをやります。
また、以下は、注文等を行う自作関数になります。
OpenOrders()は、現在持っているポジションのロット数を取得する。
SendOrder()は、買い注文、または、売り注文を発行する。
CloseOrder()は、現在持っているポジションをクローズする。
MT4が用意している関数OrderLots(), OrderSend(), OrderClose()などを 少し使いやすくしているものです。
OnInit()は、EAが最初に起動された時に呼ばれる関数です。OnTick()は、トレード中、定期的(ティックが動くたびに動作:EAの作りにもよりますが毎秒くらいに呼び出されると思って頂いて良いかと)に実行される関数です。この中で、チャートの状態を確認、注文条件を満たしたら、新規注文、決済注文を行う、といったことをやります。
また、以下は、注文等を行う自作関数になります。
OpenOrders()は、現在持っているポジションのロット数を取得する。
SendOrder()は、買い注文、または、売り注文を発行する。
CloseOrder()は、現在持っているポジションをクローズする。
MT4が用意している関数OrderLots(), OrderSend(), OrderClose()などを 少し使いやすくしているものです。
/// ===================
/// EA_xxx.mp4
/// xxxx エキスパートプログラム
/// ===================
#property link "http://xxxxx"
#include
enum trends
{
TREND_NOSET=-1,
TREND_NONE,
TREND_LONG,
TREND_SHORT,
};
//internal parameter
int CurrentTrend = TREND_NONE;
//for time
int current_min = -1;
int current_hour = -1;
//for check error
double ordered_open = -1;
//+------------------------------------------------------------------+
//| 初期化関数 |
//+------------------------------------------------------------------+
int OnInit()
{
static int counted = 0;
int limit = Bars - counted;
counted = Bars;
//過去データから現在のトレンドを更新
for(int cnt=limit-1; cnt>=1; cnt--){
CurrentTrend = CheckTrend(cnt);
}
return(0);
}
void OnDeinit(const int reason)
{
}
// 現在のトレンドを判定
int CheckTrend(int position)
{
//トレンドなしとする
int new_trend = TREND_NONE;
/* トレンド判定処理を実装 */
/* new_trendに判定したトレンド(TREND_LONG、TREND_SHORT、TREND_NONEなど)を設定 */
return(new_trend);
}
// エントリ判定
void EntrySignal(int newtrend)
{
// オープンポジションの計算
double pos = OpenOrders(MagicNumber);
bool order_buy = False;
bool order_sell = False;
if(newtrend == TREND_LONG){
/* 上昇トレンドの時の判定処理を行う */
/* 買いポジションを持つ場合はorder_buy=Trueを設定 */
}
else if(newtrend == TREND_SHORT){
/* 下降トレンドの時の判定処理を行う */
/* 売りポジションを持つ場合はorder_sell=Trueを設定 */
}
else if(newtrend == TREND_RENGE){
/* トレンドがない時の判定処理を行う */
/* 買いポジションを持つ場合はorder_buy=Trueを設定 */
/* 売りポジションを持つ場合はorder_sell=Trueを設定 */
}
//買い注文
bool RO = TRUE;
if( order_buy && (ordered_open == -1) ){
// 買い注文処理
// 売りポジションが残っていたら決済する
if( pos<0 ){
RO = CloseOrder(Symbol(), OP_SELL, Slippage, MagicNumber, clrBlueViolet);
}
// 決済が成功したか確認
if( RO ){
// 既に買いポジションを持っていないか確認
if ( pos<=0 ){
// 買い注文発行
if(SendOrder(OP_BUY, order_lots, Ask, stop_loss, stop_take, Slippage, MagicNumber, COMMENT_BBR)){
// 注文完了を保持(すぐにポジションクローズしてしまわないように)
ordered_open = open_0;
order_count_Bbr++;
}
}
}
}
//売り注文
if( order_sell && (ordered_open == -1) ){
// 売り注文処理
// 買いポジションが残っていたら決済する
if ( pos>0 ){
RO = CloseOrder(Symbol(), OP_BUY, Slippage, MagicNumber, clrBlueViolet);
}
// 決済が成功したか確認
if( RO ){
// 既に売りポジションを持っていないか確認
if ( pos>=0 ){
// 売り注文発行
if(SendOrder(OP_SELL, order_lots, Bid, stop_loss, stop_take, Slippage, MagicNumber, COMMENT_BBR)){
// 注文完了を保持(すぐにポジションクローズしてしまわないように)
ordered_open = open_0;
order_count_Bbr++;
}
}
}
}
}
// エグジット関数
void ExitPosition(int newtrend)
{
// オープンポジションの計算
double pos = OpenOrders(MagicNumber);
bool order_buy = False;
bool order_sell = False;
// 買いクローズ
/* 買いポジションをクローズするかの判定 */
/* クローズする場合はorder_buy=Trueを設定 */
// 売りクローズ
/* 売りポジションをクローズするかの判定 */
/* クローズする場合はorder_sell=Trueを設定 */
// 実行
if( order_buy && pos > 0 && (ordered_open == -1) ){
//買いポジションをクローズ
CloseOrder(Symbol(), OP_BUY, Slippage, MagicNumber, arrow_color);
}
if( order_sell && pos < 0 && (ordered_open == -1) ){
//売りポジションをクローズ
CloseOrder(Symbol(), OP_SELL, Slippage, MagicNumber, arrow_color);
}
}
// スタート関数
void OnTick()
{
MqlDateTime MqlTime;
datetime time = TimeCurrent(MqlTime);
// ↓この間は、必ずいる処理ではない
// 必要以上に動作しないよう、10秒毎に動作するようにする(ただし、時分が変わっている場合は除く)
if( ( current_hour == MqlTime.hour && current_min == MqlTime.min && MqlTime.sec%10 != 0 ) ){
return;
}
// 短い期間で、ポジションのオープンとクローズの条件が満たされた場合、何度も注文が繰り返されないよう制限をかけておく
if(order_count > 2){
Print("order count over!! >> ", order_count);
return;
}
// ↑この間は、必ずいる処理ではない
// トレード足(timeframe)に応じて1サイクルの経過で、注文済み状態を初期化
double open_0 = iOpen(NULL, timeframe, 0); //1つ前の足の始値
if( ordered_open != open_0 ){
order_count = 0;
current_hour = MqlTime.hour;
current_min = MqlTime.min;
ordered_open = -1;
}
// トレンド判定
int newtrend=CheckTrend(0);
// 売買ポジションのエグジット
ExitPosition(newtrend);
// エントリーシグナル
if((Ask - Bid)/Point <= 許容スプレッド){
EntrySignal(newtrend);
}
else{
Print("Ask - Bid = ", (Ask - Bid)/Point);
}
// 現在トレンドを更新
CurrentTrend=newtrend;
}
コメント
[…] 「自動売買プログラム(EA)フォーマット」で記載したEAプログラムフォーマットをベースに作成しています。 こちらに記載している内容については省略しています。 プログラム経験者(C言語とか)、もしくは、ちょっとプログラムの勉強をしたら、使っているMT4で用意されている関数の仕様をHelpやネット検索で調べれば、比較的簡単に分かるレベルなのではないかと思います。 […]