見出し画像

カジノのモンテカルロ法を使ったEAのサンプル

モンテカルロ法のMQLのサンプルです。

個人的にモンテカルロ法は好きじゃない。マーチンゲールのほうが好きだ。

モンテカルロ法は微妙に勝ち負けを繰り返す展開なら勝てるけど、負けを引きずると負け越しが発生する可能性があるのでマーチンみたいに勝てばすべて捲れるわけじゃない。

捲れてないのにリセットされるので、もやる瞬間がでてくるんだ。

さらに連戦連勝をしてもしょぼ勝ちになってしまうので、あんまりお金は増えない。


//+------------------------------------------------------------------+
//|                                              MonteCarloEA_RR1_1.mq4 |
//|                                      Copyright 2024, Your Name |
//|                                             https://www.yourwebsite.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Your Name"
#property link      "https://www.yourwebsite.com"
#property version   "1.00"
#property strict

// 入力パラメータ
input double InitialLotSize = 0.01;  // 初期ロットサイズ
input int MagicNumber = 12345;       // マジックナンバー
input double StopLoss = 500;          // ストップロス(ポイント)
input double TakeProfit = 500;        // テイクプロフィット(ポイント)

// グローバル変数
double sequence[100];
int sequenceSize;
bool isInitialized = false;
int lastOrderTicket = 0;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
    // 初期化
    sequenceSize = 3;
    sequence[0] = 1;
    sequence[1] = 2;
    sequence[2] = 3;
    
    if (!isInitialized)
    {
        InitializeFromHistory();
        isInitialized = true;
    }
    
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
    // オープンポジションがある場合は何もしない
    if (OrdersTotal() > 0) return;
    
    // 新しいポジションを開く
    double lotSize = CalculateMonteCarloLotSize();
    int ticket = OpenPosition(lotSize);
    
    if (ticket > 0)
    {
        Print("新しいポジションを開きました。チケット番号: ", ticket, " ロットサイズ: ", lotSize);
    }
}

//+------------------------------------------------------------------+
//| モンテカルロ法でロットサイズを計算                               |
//+------------------------------------------------------------------+
double CalculateMonteCarloLotSize()
{
    // ロットサイズの計算
    double lotSize = (sequence[0] + sequence[sequenceSize - 1]) * InitialLotSize;
    
    // 直前の取引結果の処理
    if (OrdersHistoryTotal() > 0)
    {
        for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)
        {
            if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) &&
                OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber &&
                OrderTicket() > lastOrderTicket)
            {
                lastOrderTicket = OrderTicket();
                bool isWin = (OrderProfit() > 0);
                UpdateSequence(isWin, lotSize);
                break; // 最新の取引のみを処理
            }
        }
    }
    
    // デバッグ情報の出力
    PrintSequence();
    
    return NormalizeDouble(lotSize, 2);
}

//+------------------------------------------------------------------+
//| 数列を更新                                                       |
//+------------------------------------------------------------------+
void UpdateSequence(bool isWin, double lotSize)
{
    if (isWin)
    {
        // 勝った場合、数列の両端を削除
        if (sequenceSize > 2)
        {
            for (int j = 0; j < sequenceSize - 2; j++)
            {
                sequence[j] = sequence[j + 1];
            }
            sequenceSize -= 2;
        }
        else
        {
            // 数列が空になったら終了
            sequenceSize = 0;
        }
    }
    else
    {
        // 負けた場合、ベット額を数列の最後に追加
        if (sequenceSize < ArraySize(sequence))
        {
            sequence[sequenceSize] = lotSize / InitialLotSize; // ベット額を数列に追加
            sequenceSize++;
        }
    }
    
    if (sequenceSize == 0)
    {
        // 数列が空になったら初期化
        sequence[0] = 1;
        sequence[1] = 2;
        sequence[2] = 3;
        sequenceSize = 3;
    }
}

//+------------------------------------------------------------------+
//| 取引履歴から初期状態を設定                                       |
//+------------------------------------------------------------------+
void InitializeFromHistory()
{
    int historyCount = 0;
    
    for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)
    {
        if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) &&
            OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
        {
            historyCount++;
            bool isWin = (OrderProfit() > 0);
            double usedLotSize = OrderLots() / InitialLotSize;
            
            UpdateSequence(isWin, usedLotSize);
            
            // 最新の20取引まで遡る
            if (historyCount >= 20) break;
        }
    }
}

//+------------------------------------------------------------------+
//| 新しいポジションを開く                                           |
//+------------------------------------------------------------------+
int OpenPosition(double lotSize)
{
    int ticket = 0;
    double price = 0;
    double sl = 0;
    double tp = 0;
    
    if (MathRand() % 2 == 0) // ランダムに買いまたは売りを選択
    {
        price = Ask;
        sl = NormalizeDouble(price - StopLoss * Point, Digits);
        tp = NormalizeDouble(price + TakeProfit * Point, Digits);
        ticket = OrderSend(Symbol(), OP_BUY, lotSize, price, 3, sl, tp, "MonteCarloEA", MagicNumber, 0, clrGreen);
    }
    else
    {
        price = Bid;
        sl = NormalizeDouble(price + StopLoss * Point, Digits);
        tp = NormalizeDouble(price - TakeProfit * Point, Digits);
        ticket = OrderSend(Symbol(), OP_SELL, lotSize, price, 3, sl, tp, "MonteCarloEA", MagicNumber, 0, clrRed);
    }
    
    return ticket;
}

//+------------------------------------------------------------------+
//| 数列をプリント                                                   |
//+------------------------------------------------------------------+
void PrintSequence()
{
    string sequenceStr = "";
    for (int i = 0; i < sequenceSize; i++)
    {
        sequenceStr += DoubleToString(sequence[i], 2);
        if (i < sequenceSize - 1) sequenceStr += ",";
    }
    Print("Sequence: ", sequenceStr);
}

Claude 3.5 Sonnetで生成しました。


コードは著作権フリーです。自由に使ってね!

よろしければサポートお願いします! いただいたサポートはクリエイターとしての活動費に使わせていただきます!