#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

#include <Trade/Trade.mqh>

CTrade           trade;
CPositionInfo    pos;
COrderInfo       ord;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
input group "*** Trading Inputs ***"

enum SystemType { Forex=0, Bitcoin=1, _Gold=2, US_Indeces=3 };
input SystemType Stype = 0;
int SysChoice;

input double RiskPercent = 3;   // Risk as % of Trading capital
input ENUM_TIMEFRAMES Timeframe = PERIOD_CURRENT; // Time frame to run
input int    InpMagic = 298347; // EA identification no
input string TradeComment = "Scalpin Robot";
input int MaxOrders = 8; // Maximum allowed open orders

enum StarHour { Inactive=0, _0100=1, _0200=2, _0300=3, _0400=4, _0500=5, _0600=6, _0700=7, _0800=8, _0900=9, _1000=10, _1100=11, _1200=12, _1300=13, _1400=14, _1500=15, _1600=16, _1700=17, _1800=18, _1900=19, _2000=20, _2100=21, _2200=22, _2300=23 };
input StarHour SHInput = 0; // Start Hour

enum EndHour { Inactive=0, _0100=1, _0200=2, _0300=3, _0400=4, _0500=5, _0600=6, _0700=7, _0800=8, _0900=9, _1000=10, _1100=11, _1200=12, _1300=13, _1400=14, _1500=15, _1600=16, _1700=17, _1800=18, _1900=19, _2000=20, _2100=21, _2200=22, _2300=23 };
input EndHour EHInput = 0; // End Hour

int SHChoice;
int EHChoice;

int    BarsN = 5;
int    ExpirationBars = 100;
double OrderDistPoints = 100;
double Tppoints, Slpoints, TslTriggerPoints, TslPoints;


//Adcionando Filters



input group "=== Forex Trading Inputs ==="
input int TppointsInput = 200; // Take Profit (10 points = 1 pip)
input int SlpointsInput = 200; // Stoploss Points (16 points = 1 pip)
input int TslTriggerPointsInput = 15; // Points in profit before Trailing SL is activated (10 points = 1 pip)
input int TslPointsInput = 10; // Trailing Stop Loss (10 points = 1 pip)

input group "=== Crypto Related Input === (effective only under Bitcoin profile)"
input double TPasPct = 0.4; // TP as % of Price
input double SLasPct = 0.4; // SL as%of Price
input double TSLasPctofTP = 5; // Trail SL as % of TP
input double TSLTgrasPctofTP = 7; // Trigger of Trail SL % of TP

input group "=== Gold Related Input === (effective only under Gold profile)"
input double TPasPctGold = 0.2; // TP as % of Price
input double SLasPctGold = 0.2; // SL as% of Price
input double TSLasPctofTPGold = 5; // Trail SL as % of TP
input double TSLTgrasPctofTPGold = 7; // Trigger of Trail SL % of TP

input group "=== Indices Related Input === (effective only under Indices profile)"
input double TPasPctIndices = 0.2; // TP as % of Price
input double SLasPctIndices = 0.2; // SL as 5% of Price
input double TSLasPctofTPIndices = 5; // Trail SL as % of TP
input double TSLTgrasPctofTPIndices = 7; // Trigger of Trail SL % of TP

int OnInit() 
{
    //---
    trade.SetExpertMagicNumber(InpMagic);
    ChartSetInteger(0, CHART_SHOW_GRID, false);

    SHChoice = SHInput;
    EHChoice = EHInput;

    SysChoice = Stype;

    Tppoints = TppointsInput;
    Slpoints = SlpointsInput;
    TslTriggerPoints = TslTriggerPointsInput;
    TslPoints = TslTriggerPointsInput;

    return (INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) 
{
    //---
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick() 
{
    //---
    TrailStop();

    if (!IsNewBar()) return;

    MqlDateTime time;
    TimeToStruct(TimeCurrent(), time);

    int Hournow = time.hour;

    if (Hournow < SHChoice) { CloseAllOrders(); return; }
    if (Hournow >= EHChoice && EHChoice != 0) { CloseAllOrders(); return; }

    if (SysChoice == 1) {
        double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
        Tppoints = ask * TPasPct;
        Slpoints = ask * SLasPct;
        OrderDistPoints = Tppoints / 2;
        TslPoints = Tppoints * TSLasPctofTP / 100;
        TslTriggerPoints = Tppoints * TSLTgrasPctofTP / 100;
    }

    int BuyTotal = 0;
    int SellTotal = 0;

    for (int i = PositionsTotal() - 1; i >= 0; i--) {
        pos.SelectByIndex(i);
        if (pos.Symbol() == _Symbol && pos.Magic() == InpMagic) {
            if (pos.PositionType() == POSITION_TYPE_BUY) BuyTotal++;
            if (pos.PositionType() == POSITION_TYPE_SELL) SellTotal++;
        }
    }

    for (int i = OrdersTotal() - 1; i >= 0; i--) {
        ord.SelectByIndex(i);
        if (ord.Symbol() == _Symbol && ord.Magic() == InpMagic) {
            if (ord.OrderType() == ORDER_TYPE_BUY_STOP) BuyTotal++;
            if (ord.OrderType() == ORDER_TYPE_SELL_STOP) SellTotal++;
        }
    }

    // Limit the total number of orders to MaxOrders
    if (BuyTotal + SellTotal < MaxOrders) {
        if (BuyTotal <= 0) {
            double high = findHigh();
            if (high > 0) {
                SendBuyOrder(high);
            }
        }

        if (SellTotal <= 0) {
            double low = findLow();
            if (low > 0) {
                SendSellOrder(low);
            }
        }
    }
}

//+------------------------------------------------------------------+
double findHigh() 
{
    double highestHigh = 0;
    for (int i = 0; i < 200; i++) {
        double high = iHigh(_Symbol, Timeframe, i);
        if (i > BarsN && iHighest(_Symbol, Timeframe, MODE_HIGH, BarsN * 2 + 1, i - BarsN) == i) {
            if (high > highestHigh) {
                return high;
            }
        }
        highestHigh = MathMax(high, highestHigh);
    }
    return -1;
}

double findLow() 
{
    double LowestLow = DBL_MAX;
    for (int i = 0; i < 200; i++) {
        double Low = iLow(_Symbol, Timeframe, i);
        if (i > BarsN && iLowest(_Symbol, Timeframe, MODE_LOW, BarsN * 2 + 1, i - BarsN) == i) {
            if (Low < LowestLow) {
                return Low;
            }
        }
        LowestLow = MathMin(Low, LowestLow);
    }
    return -1;
}

bool IsNewBar() 
{
    static datetime previousTime = 0;
    datetime currentTime = iTime(_Symbol, Timeframe, 0);
    if (previousTime != currentTime) {
        previousTime = currentTime;
        return true;
    }
    return false;
}

void SendBuyOrder(double entry) 
{
    double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
    if (ask > entry - OrderDistPoints * _Point) return;

    double tp = entry + Tppoints * _Point;
    double sl = entry - Slpoints * _Point;

    double lots = 0.01;
    if (RiskPercent > 0) lots = calcLots(entry - sl);

    datetime expiration = iTime(_Symbol, Timeframe, 0) + ExpirationBars * PeriodSeconds(Timeframe);

    trade.BuyStop(lots, entry, _Symbol, sl, tp, ORDER_TIME_SPECIFIED, expiration);
}

void SendSellOrder(double entry) 
{
    double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
    if (bid < entry + OrderDistPoints * _Point) return;

    double tp = entry - Tppoints * _Point;
    double sl = entry + Slpoints * _Point;

    double lots = 0.01;
    if (RiskPercent > 0) lots = calcLots(sl - entry);

    datetime expiration = iTime(_Symbol, Timeframe, 0) + ExpirationBars * PeriodSeconds(Timeframe);

    trade.SellStop(lots, entry, _Symbol, sl, tp, ORDER_TIME_SPECIFIED, expiration);
}

double calcLots(double slPoints) 
{
    double risk = AccountInfoDouble(ACCOUNT_BALANCE) * RiskPercent / 100;

    double ticksize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
    double tickvalue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
    double lotstep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
    double minvolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
    double maxvolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
    double volumelimit = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_LIMIT);

    double moneyPerLotstep = slPoints / ticksize * tickvalue * lotstep;
    double lots = MathFloor(risk / moneyPerLotstep) * lotstep;

    if (volumelimit != 0) lots = MathMin(lots, volumelimit);
    if (maxvolume != 0) lots = MathMin(lots, SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX));
    if (minvolume != 0) lots = MathMax(lots, SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN));
    lots = NormalizeDouble(lots, 2);

    return lots;
}

void CloseAllOrders() 
{
    for (int i = OrdersTotal() - 1; i >= 0; i--) {
        ord.SelectByIndex(i);
        ulong ticket = ord.Ticket();
        if (ord.Symbol() == _Symbol && ord.Magic() == InpMagic) {
            trade.OrderDelete(ticket);
        }
    }
}

void TrailStop() 
{
    double sl = 0;
    double tp = 0;

    double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
    double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);

    for (int i = PositionsTotal() - 1; i >= 0; i--) {
        if (pos.SelectByIndex(i)) {
            ulong ticket = pos.Ticket();

            if (pos.Magic() == InpMagic && pos.Symbol() == _Symbol) {

                if (pos.PositionType() == POSITION_TYPE_BUY) {
                    if (bid - pos.PriceOpen() > TslTriggerPoints * _Point) {
                        tp = pos.TakeProfit();
                        sl = bid - (TslPoints * _Point);

                        if (sl > pos.StopLoss() && sl != 0) {
                            trade.PositionModify(ticket, sl, tp);
                        }
                    }
                } else if (pos.PositionType() == POSITION_TYPE_SELL) {
                    if (ask + (TslTriggerPoints * _Point) < pos.PriceOpen()) {
                        tp = pos.TakeProfit();
                        sl = ask + (TslPoints * _Point);

                        if (sl < pos.StopLoss() && sl != 0) {
                            trade.PositionModify(ticket, sl, tp);
                        }
                    }
                }
            }
        }
    }
}
voce consegue criar um indicador com base nesse robo ?

inves de ele abrir ordens ele apenas mostrar setas de possiveis entradas que seriam no robo uma abertura de ordem e stoploss e possivel take?