🎉

MQL4でモンテカルロ法を計算する

2024/08/18に公開
double CalculateMonteCarloLotSize()
{
    static double sequence[100] = {1, 2, 3}; // 初期数列
    static int sequenceSize = 3;          // 初期数列の長さ
    static bool isInitialized = false;    // 初期化フラグ
    static int lastOrderTicket = 0;       // 最後に処理した注文のチケット番号

    // 初期化(EA起動時に一度だけ実行)
    if (!isInitialized)
    {
        InitializeFromHistory(sequence, sequenceSize);
        isInitialized = true;
    }

    // ロットサイズの計算
    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);
                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++;
                    }
                }
                break; // 最新の取引のみを処理
            }
        }
    }

    // デバッグ情報の出力
    string sequenceStr = "";
    for (int i = 0; i < sequenceSize; i++)
    {
        sequenceStr += DoubleToString(sequence[i], 2);
        if (i < sequenceSize - 1) sequenceStr += ",";
    }
    Print("Lot Size: ", DoubleToString(lotSize, 2), " Sequence: ", sequenceStr);

    if (sequenceSize == 0)
    {
        // 数列が空になったら初期化
        sequence[0] = 1;
        sequence[1] = 2;
        sequence[2] = 3;
        sequenceSize = 3;
    }

    return NormalizeDouble(lotSize, 2);
}


// TradeHistoryから初期状態を設定
void InitializeFromHistory(double &sequence[], int &sequenceSize)
{
    int historyCount = 0;
    sequenceSize = 3;
    sequence[0] = 1;
    sequence[1] = 2;
    sequence[2] = 3;
    
    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;
            
            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] = usedLotSize;
                    sequenceSize++;
                }
            }
            
            if (sequenceSize == 0)
            {
                sequence[0] = 1;
                sequence[1] = 2;
                sequence[2] = 3;
                sequenceSize = 3;
            }
            
            // 最新の20取引まで遡る
            if (historyCount >= 20) break;
        }
    }
}

Discussion