
プログラムを学ぶ第一歩は、既存のプログラムを動かしたり、改造したりすることです。
サンプルプログラムを見てみよう
まずはスクリプトの構成を見てみましょう。はじめての方は暗号に見えるかもしれません。
ファイル構成
- 1~5行目 ヘッダーコメント ファイルの作者等のコメント
- 6~9行目 ファイル情報 バージョンや著作権などの設定
- 10~18行目 input変数の宣言 EAのパラメーター設定で入力できる変数を宣言する
- 20行目 ロットの補正(設定値が1.0枚=10,000通貨単位なので、補正しています。証券会社によって違うので適宜変えてください。楽天MT4は1.0枚=100,000通貨単位です)
- 21~246行目 状態クラスの定義
- 247~262行目 起動時の処理(EAの起動時に実行)
- 263~271行目 終了時の処理
- 272~298行目 ここがメイン。新しい値動きが追加されるたびに実行される処理。状態変化がないかチェックして、買いシグナル、売りシグナルが発生したら処理を行い次の状態に移行する。
- 304~最終行 売りシグナル、買いシグナル判定関数。ここを自由に変更してください。
//+------------------------------------------------------------------+
//| template.mq4 |
//| castanet |
//| https://fx.castanet.tokyo |
//+------------------------------------------------------------------+
#property copyright "castanet"
#property link "https://fx.castanet.tokyo"
#property version "1.00"
#property strict
//--- input parameters
input double sell_threshold=75;
input double buy_threshold=25;
input double set_lots=2;
input int stop_pips=1000;
input int limit_pips=200;
input int stop_enable=0;
input int limit_enable=0;
input int magic_number = 10415518;
double lots = set_lots / 10.0;
// 状態基底クラス
class CStatus {
private:
int m_status;
protected:
static int g_ticket;
static int ticket() { return g_ticket; }
void ticket(int tk) { g_ticket = tk; }
public:
CStatus(int st) { m_status = st; }
virtual int sell_signal() { return status(); }
virtual int buy_signal() { return status(); }
virtual int check() { return status(); }
int status() { return m_status; }
};
int CStatus::g_ticket = -1;
class init_pos : public CStatus {
public:
init_pos() : CStatus(1) {}
virtual int sell_signal() {
double stop_level = 0;
if (stop_enable) {
stop_level = NormalizeDouble(Bid + stop_pips * Point, Digits);
}
double limit_level = 0;
if (limit_enable) {
limit_level = NormalizeDouble(Bid - limit_pips * Point, Digits);
}
Print("Bid=", Bid, "Stop=", stop_level, "Limit=", limit_level);
int result = OrderSend( Symbol(), OP_SELL, lots, Bid, 30, stop_level, limit_level, NULL, magic_number, 0, Red );
int ErrCode = GetLastError();
if (ErrCode == 0) {
ticket(result);
return 5;
}
else {
Print( "ErrCode=" + (string)ErrCode );
return status();
}
}
virtual int buy_signal() {
double stop_level = 0;
if (stop_enable) {
stop_level = NormalizeDouble(Ask - stop_pips * Point, Digits);
}
double limit_level = 0;
if (limit_enable) {
limit_level = NormalizeDouble(Ask + limit_pips * Point, Digits);
}
Print("Ask=", Ask, "Stop=", stop_level);
int result = OrderSend( Symbol(), OP_BUY, lots, Ask, 30, stop_level, limit_level, NULL, magic_number, 0, Blue );
int ErrCode = GetLastError();
if (ErrCode == 0) {
ticket(result);
return 4;
}
else {
Print( "ErrCode=" + (string)ErrCode );
return status();
}
}
virtual int check() {
// オーダー情報取得
for ( int i = 0; i < OrdersTotal(); i++ ){
// オーダー選択
if ( OrderSelect( i, SELECT_BY_POS, MODE_TRADES ) ) {
// オーダー確認
if ( OrderMagicNumber() != magic_number || OrderSymbol() != Symbol() ) {
continue;
}
// オーダーあり
ticket(OrderTicket());
if ( OrderType() == OP_BUY ) {
return 2;
}
else if ( OrderType() == OP_SELL ) {
return 3;
}
else {
// とりあえず、決済中にしておく
return 6;
}
}
}
return status();
}
};
class buy_pos : public CStatus {
public:
buy_pos() : CStatus(2) {}
virtual int sell_signal() {
// パラメータが変わってる時を考慮して、ロット数を取得
double _lots = lots;
if ( OrderSelect( ticket(), SELECT_BY_TICKET ) ) {
_lots = OrderLots();
}
int result = OrderClose( ticket(), _lots, Bid, 30, Goldenrod );
int ErrCode = GetLastError();
if (result) {
return 6;
}
else {
return status();
}
}
virtual int check() {
// オーダー選択
if ( OrderSelect( ticket(), SELECT_BY_TICKET ) ) {
if (OrderCloseTime() != 0) {
// キャンセルされた
ticket(-1);
return 1;
}
}
else {
ticket(-1);
return 1;
}
return status();
}
};
class sell_pos : public CStatus {
public:
sell_pos() : CStatus(3) {}
virtual int buy_signal() {
// パラメータが変わってる時を考慮して、ロット数を取得
double _lots = lots;
if ( OrderSelect( ticket(), SELECT_BY_TICKET ) ) {
_lots = OrderLots();
}
int result = OrderClose( ticket(), _lots, Ask, 30, Goldenrod );
int ErrCode = GetLastError();
if (result) {
return 6;
}
else {
return status();
}
}
virtual int check() {
// オーダー選択
if ( OrderSelect( ticket(), SELECT_BY_TICKET ) ) {
if (OrderCloseTime() != 0) {
// キャンセルされた
ticket(-1);
return 1;
}
}
else {
ticket(-1);
return 1;
}
return status();
}
};
class buy_order : public CStatus {
public:
buy_order() : CStatus(4) {}
virtual int check() {
// オーダー選択
if ( OrderSelect( ticket(), SELECT_BY_TICKET ) ) {
if (OrderCloseTime() != 0) {
// キャンセルされた
ticket(-1);
return 1;
}
if (OrderType() == OP_BUY) {
return 2;
}
}
else {
ticket(-1);
return 1;
}
return status();
}
};
class sell_order : public CStatus {
public:
sell_order() : CStatus(5) {}
virtual int check() {
// オーダー選択
if ( OrderSelect( ticket(), SELECT_BY_TICKET ) ) {
if (OrderCloseTime() != 0) {
// キャンセルされた
ticket(-1);
return 1;
}
if (OrderType() == OP_SELL) {
return 3;
}
}
else {
ticket(-1);
return 1;
}
return status();
}
};
class close_order : public CStatus {
public:
close_order() : CStatus(6) {}
virtual int check() {
// オーダー選択
if ( OrderSelect( ticket(), SELECT_BY_TICKET ) ) {
if (OrderCloseTime() != 0) {
ticket(-1);
return 1;
}
}
else {
ticket(-1);
return 1;
}
return status();
}
};
CStatus *current;
CStatus *StatusArray[7];
int status = 1;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit() {
//---
StatusArray[1] = new init_pos();
StatusArray[2] = new buy_pos();
StatusArray[3] = new sell_pos();
StatusArray[4] = new buy_order();
StatusArray[5] = new sell_order();
StatusArray[6] = new close_order();
status = 1;
current = StatusArray[1];
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
//---
for (int i = 1; i < 7; i++) {
delete StatusArray[i];
}
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick() {
//---
int next = status;
next = current.check();
if (next != status) {
Print("ポジションチェックで状態変化:", status, "→", next);
status = next;
}
current = StatusArray[status];
// 売りシグナルチェック
if ( is_sell_signal() ) {
next = current.sell_signal();
}
// 買いシグナルチェック
if ( is_buy_signal() ) {
next = current.buy_signal();
}
if (next != status) {
Print("シグナルで状態変化:", status, "→", next);
status = next;
}
current = StatusArray[status];
}
//+------------------------------------------------------------------+
// 売シグナル判定関数です。if文の関数を他のテクニカルインジケータ―関数に変えてみてください
bool is_sell_signal() {
bool ret = false;
if ((iRSI(NULL, 0, 14, PRICE_CLOSE, 0)) > sell_threshold) {
ret = true;
}
return ret;
}
// 買シグナル判定関数です。if文の関数を他のテクニカルインジケータ―関数に変えてみてください
bool is_buy_signal() {
bool ret = false;
if ((iRSI(NULL, 0, 14, PRICE_CLOSE, 0)) < buy_threshold) {
ret = true;
}
return ret;
}

