Juan.arana92/PRUEBA1_0947_150825

112 lines
4.5 KiB
Text
Raw Permalink Normal View History

2025-08-15 15:48:09 +00:00
//+------------------------------------------------------------------+
//| SMC_FVG_Liquidity_EA.mq5 |
//+------------------------------------------------------------------+
#property strict
input double RiskPct = 0.5; // % riesgo por trade
input ENUM_TIMEFRAMES HTF = PERIOD_H1; // Marco para bias
input ENUM_TIMEFRAMES LTF = PERIOD_M5; // Marco para FVG/entrada
input int FVGLookback = 100; // Velas a escanear LTF
input int StopBufferPoints = 30; // Colchón extra para SL
input bool AllowLong = true;
input bool AllowShort = true;
// --- utilidades
double GetAccountRiskValue(){ return(AccountInfoDouble(ACCOUNT_BALANCE) * RiskPct/100.0); }
double PipToPoints(double pips){ return(pips * (_Point==0.00001 || _Point==0.001 ? 10 : 1)); }
// --- bias HTF simple (puedes mejorar con BOS/CHoCH)
int BiasHTF() {
// 1 = alcista, -1 = bajista, 0 = neutro
MqlRates r[]; if(!CopyRates(_Symbol, HTF, 0, 200, r)) return 0;
if(r[1].close > r[1].open && r[2].close > r[2].open) return 1;
if(r[1].close < r[1].open && r[2].close < r[2].open) return -1;
return 0;
}
// --- detección básica de FVG (tres velas): gap entre vela1.high y vela3.low (ventas) o vela1.low y vela3.high (compras)
bool FindFVG(int direction, double &fvgTop, double &fvgBottom){
MqlRates c[]; if(!CopyRates(_Symbol, LTF, 0, FVGLookback, c)) return false;
ArraySetAsSeries(c,true);
for(int i=2; i<FVGLookback; i++){
double prevHigh = c[i].high, prevLow = c[i].low;
double midHigh = c[i-1].high, midLow = c[i-1].low;
double nextHigh = c[i-2].high, nextLow = c[i-2].low;
if(direction<0){ // short: hueco bajista (prevHigh < nextLow)
if(prevHigh < nextLow){
fvgTop = nextLow; fvgBottom = prevHigh; return true;
}
} else if(direction>0){ // long: hueco alcista (prevLow > nextHigh)
if(prevLow > nextHigh){
fvgTop = prevLow; fvgBottom = nextHigh; return true;
}
}
}
return false;
}
// --- barrida simple: rompe el máximo/mínimo previo reciente y regresa
bool LiquiditySweep(int direction){
MqlRates c[]; if(!CopyRates(_Symbol, LTF, 0, 50, c)) return false;
ArraySetAsSeries(c,true);
double recentHigh = c[10].high, recentLow = c[10].low;
for(int i=1;i<=10;i++){ recentHigh = MathMax(recentHigh, c[i].high); recentLow = MathMin(recentLow, c[i].low); }
if(direction<0){ // short: barrió arriba y vuelve debajo
return (iHigh(_Symbol,LTF,1) > recentHigh && Close[0] < recentHigh);
} else if(direction>0){ // long: barrió abajo y vuelve encima
return (iLow(_Symbol,LTF,1) < recentLow && Close[0] > recentLow);
}
return false;
}
// --- tamaño de lote por SL en puntos
double CalcLotBySL(double slPrice){
double risk = GetAccountRiskValue();
double slPoints = MathAbs((slPrice - SymbolInfoDouble(_Symbol,SYMBOL_BID))/_Point);
double tickValue = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
double tickSize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
if(slPoints<=0 || tickValue<=0 || tickSize<=0) return 0.0;
double valuePerPointPerLot = tickValue / (tickSize/_Point);
double lot = risk / (slPoints * valuePerPointPerLot);
double minLot = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
double step = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
// normaliza
lot = MathMax(minLot, MathFloor(lot/step)*step);
return lot;
}
// --- ejecución
void TryEntry(){
int bias = BiasHTF(); if(bias==0) return;
double fvgTop, fvgBottom;
if(!FindFVG(bias, fvgTop, fvgBottom)) return;
if(!LiquiditySweep(bias)) return;
// definimos precio de entrada en el borde del FVG
double ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
if(bias<0 && AllowShort){
double entry = fvgBottom; // vender en rebote al borde inferior del FVG bajista
double sl = fvgTop + StopBufferPoints*_Point;
double lot = CalcLotBySL(sl);
if(lot>0 && bid>=entry){ // condición simple, podrías usar órdenes pendientes
trade.Sell(lot,_Symbol,bid,sl,0,"SMC short");
}
}
if(bias>0 && AllowLong){
double entry = fvgTop; // comprar en rebote al borde superior del FVG alcista
double sl = fvgBottom - StopBufferPoints*_Point;
double lot = CalcLotBySL(sl);
if(lot>0 && ask<=entry){
trade.Buy(lot,_Symbol,ask,sl,0,"SMC long");
}
}
}
#include <Trade/Trade.mqh>
CTrade trade;
int OnInit(){ return(INIT_SUCCEEDED); }
void OnTick(){ TryEntry(); }