//+------------------------------------------------------------------+
//|                                             TradingRobot.mq5    |
//|                        Copyright 2023, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+

input int    InputMagic = 3331; // Alterado para evitar conflito com variável global
input double MaxSpread = 1.0;
input double Lot = 0.1;
input double SL = 7.0;
input double TP = 0.7;
input double jumpStepBuy = 0.5;
input double jumpStepSell = 0.5;
input double jumpTimeSec = 0.5;
input bool   invertJump = true;
input bool   invertBuySell = true;
input int    SlippageOpen = 0;
input int    SlippageClose = 0;
input bool   TradeBuy = true;
input bool   TradeSell = true;
input bool   UseMM = true;
input double MM = 5;
input bool   useMoving = false;
input int    MovingPeriod = 10;
input bool   noMoreTrades = false;

double pAsk = 0;
double pBid = 0;
double point;
bool canBuy = true;
bool canSell = true;
bool imaBuy = true;
bool imaSell = true;

double ArrPrice[10000];
int    ArrTimer[10000];

double l = 0;
int nd;

void OnInit()
{
    Comment("");
    nd = 2; // Default to two decimal places
    point = SymbolInfoDouble(Symbol(), SYMBOL_POINT);

    ArrayInitialize(ArrPrice, 0);
    ArrayInitialize(ArrTimer, 0);
    EventSetTimer(1); // Set timer to call OnTimer every second
}

void OnTimer()
{
    pAsk = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
    pBid = SymbolInfoDouble(Symbol(), SYMBOL_BID);

    if(TryClose()) return;

    CalcLot();
    checkMoving();
    checkJump();

    TryTrade();
}

void CalcLot()
{
    if(UseMM)
    {
        l = NormalizeDouble(AccountInfoDouble(ACCOUNT_EQUITY) * MM / 10000, nd);
        if(l < SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MIN))
            l = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MIN);
        if(l > SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MAX))
            l = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MAX);
    }
    else
    {
        l = Lot;
    }
}

bool TryTrade()
{
    int total = PositionsTotal();
    
    MqlTradeRequest request;
    MqlTradeResult result;

    // Prepare request defaults
    request.symbol = Symbol();
    request.volume = l;
    request.sl = 0; // You may want to set SL and TP values
    request.tp = 0;
    request.slippage = SlippageOpen;
    request.magic = InputMagic;

    if(TradeBuy && canBuy && imaBuy && !noMoreTrades && (pAsk - pBid) / point <= MaxSpread)
    {
        if(!invertBuySell && MyOrdersBuyTotal(InputMagic) < 1)
        {
            request.action = TRADE_ACTION_BUY;
            request.price = pAsk;

            if(!OrderSend(request, result))
            {
                Print("Error opening buy order: ", result.retcode);
            }
        }
        if(invertBuySell && MyOrdersSellTotal(InputMagic) < 1)
        {
            request.action = TRADE_ACTION_SELL;
            request.price = pBid;

            if(!OrderSend(request, result))
            {
                Print("Error opening sell order: ", result.retcode);
            }
        }
    }

    if(TradeSell && canSell && imaSell && !noMoreTrades && (pAsk - pBid) / point <= MaxSpread)
    {
        if(!invertBuySell && MyOrdersSellTotal(InputMagic) < 1)
        {
            request.action = TRADE_ACTION_SELL;
            request.price = pBid;

            if(!OrderSend(request, result))
            {
                Print("Error opening sell order: ", result.retcode);
            }
        }
        if(invertBuySell && MyOrdersBuyTotal(InputMagic) < 1)
        {
            request.action = TRADE_ACTION_BUY;
            request.price = pAsk;

            if(!OrderSend(request, result))
            {
                Print("Error opening buy order: ", result.retcode);
            }
        }
    }

    return (total == PositionsTotal());
}

bool TryClose()
{
    double p, moneyProfit, minProfit, maxLose;
    int total = PositionsTotal();

    for(int i = 0; i < total; i++)
    {
        ulong ticket = PositionGetTicket(i);
        if(PositionSelectByTicket(ticket) && PositionGetInteger(POSITION_MAGIC) == InputMagic && PositionGetString(POSITION_SYMBOL) == Symbol())
        {
            if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
            {
                p = PositionGetDouble(POSITION_PRICE_OPEN) - SymbolInfoDouble(Symbol(), SYMBOL_ASK);
                moneyProfit = pipsProfit(PositionGetDouble(POSITION_VOLUME), p);
                minProfit = pipsProfit(PositionGetDouble(POSITION_VOLUME), TP * point);
                maxLose = pipsProfit(PositionGetDouble(POSITION_VOLUME), -SL * point);
                if(moneyProfit + PositionGetDouble(POSITION_COMMISSION) >= minProfit || moneyProfit + PositionGetDouble(POSITION_COMMISSION) <= maxLose)
                {
                    if(!PositionClose(ticket))
                        Print("Error closing sell position: ", GetLastError());
                }
            }
            else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
            {
                p = SymbolInfoDouble(Symbol(), SYMBOL_BID) - PositionGetDouble(POSITION_PRICE_OPEN);
                moneyProfit = pipsProfit(PositionGetDouble(POSITION_VOLUME), p);
                minProfit = pipsProfit(PositionGetDouble(POSITION_VOLUME), TP * point);
                maxLose = pipsProfit(PositionGetDouble(POSITION_VOLUME), -SL * point);
                if(moneyProfit + PositionGetDouble(POSITION_COMMISSION) >= minProfit || moneyProfit + PositionGetDouble(POSITION_COMMISSION) <= maxLose)
                {
                    if(!PositionClose(ticket))
                        Print("Error closing buy position: ", GetLastError());
                }
            }
        }
    }

    return (total == PositionsTotal());
}

int MyOrdersBuyTotal(int Magic)
{
    int c = 0;
    int total = PositionsTotal();

    for(int cnt = 0; cnt < total; cnt++)
    {
        if(PositionSelect(cnt))
        {
            if(PositionGetInteger(POSITION_MAGIC) == InputMagic && PositionGetString(POSITION_SYMBOL) == Symbol() && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
            {
                c++;
            }
        }
    }
    return c;
}

int MyOrdersSellTotal(int Magic)
{
    int c = 0;
    int total = PositionsTotal();

    for(int cnt = 0; cnt < total; cnt++)
    {
        if(PositionSelect(cnt))
        {
            if(PositionGetInteger(POSITION_MAGIC) == InputMagic && PositionGetString(POSITION_SYMBOL) == Symbol() && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
            {
                c++;
            }
        }
    }
    return c;
}

double calc_iMA(int iPeriod)
{
    double closePrices[];
    // Ensure the array is allocated
    ArrayResize(closePrices, iPeriod);
    // Copia os valores de fechamento de acordo com o período desejado
    CopyClose(Symbol(), PERIOD_CURRENT, 0, iPeriod, closePrices);
    
    double d = 0;
    for(int i = 0; i < iPeriod; i++)
    {
        d += closePrices[i]; // Usa o array de fechamento copiado
    }
    return d / iPeriod;
}

double pipsProfit(double lots, double pips)
{
    return (SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_VALUE) * lots * pips / point * 10);
}

void checkJump()
{
    for(int i = ArraySize(ArrPrice) - 1; i > 0; i--)
    {
        ArrPrice[i] = ArrPrice[i - 1];
        ArrTimer[i] = ArrTimer[i - 1];
    }

    ArrPrice[0] = SymbolInfoDouble(Symbol(), SYMBOL_BID); // Alterado para obter Bid
    ArrTimer[0] = GetTickCount();

    int max = ArraySize(ArrTimer) - 1;
    for(int i = 0; i < ArraySize(ArrTimer); i++)
    {
        if(ArrTimer[0] - ArrTimer[i] > jumpTimeSec * 1000 && ArrPrice[i] != 0)
        {
            max = i;
            break;
        }
    }

    for(int i = 0; i < max; i++)
    {
        double p = (SymbolInfoDouble(Symbol(), SYMBOL_BID) - ArrPrice[i]) / point; // Alterado para obter Bid
        if(!invertJump)
        {
            canSell = p >= jumpStepSell;
            canBuy = p <= -jumpStepBuy;
        }
        else
        {
            canBuy = p >= jumpStepSell;
            canSell = p <= -jumpStepBuy;
        }
    }
}

void checkMoving()
{
    double v = calc_iMA(MovingPeriod);
    double closePrices[];
    ArrayResize(closePrices, 1);
    if(CopyClose(Symbol(), PERIOD_CURRENT, 0, 1, closePrices) != 1)
    {
        return; // Handle error if CopyClose fails
    }
    imaBuy = closePrices[0] > v; // Corrigido para usar CopyClose
    imaSell = closePrices[0] < v; // Corrigido para usar CopyClose
}

//+------------------------------------------------------------------+

erros:

'slippage' - undeclared identifier	HFT_RUSSIAN_001.mq5	94	13
'TRADE_ACTION_BUY' - undeclared identifier	HFT_RUSSIAN_001.mq5	101	30
'TRADE_ACTION_SELL' - undeclared identifier	HFT_RUSSIAN_001.mq5	111	30
'TRADE_ACTION_SELL' - undeclared identifier	HFT_RUSSIAN_001.mq5	125	30
'TRADE_ACTION_BUY' - undeclared identifier	HFT_RUSSIAN_001.mq5	135	30
'PositionClose' - undeclared identifier	HFT_RUSSIAN_001.mq5	166	25
'ticket' - some operator expected	HFT_RUSSIAN_001.mq5	166	39
'PositionClose' - undeclared identifier	HFT_RUSSIAN_001.mq5	178	25
'ticket' - some operator expected	HFT_RUSSIAN_001.mq5	178	39
implicit conversion from 'number' to 'string'	HFT_RUSSIAN_001.mq5	195	27
implicit conversion from 'number' to 'string'	HFT_RUSSIAN_001.mq5	213	27
possible loss of data due to type conversion from 'uint' to 'int'	HFT_RUSSIAN_001.mq5	254	17