跳至主要內容
金融世界

MT5-分享交易程式碼

47 分鐘1 次瀏覽
MT5-分享交易程式碼

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

//| V15_Variant_3.mq5 |

//| H1 trend + M1/M5 KD/BB pullback resonance for FIRST entry only |

//| Adds still use fixed grid step 0.001 * first price. |

//| Attach on M5 or M15 recommended. |

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

#property copyright "EAM1 Training V15"

#property version "15.30"

#property description "V15-3 KD/BB pullback first-entry BUY grid"

#property strict

#include <Trade/Trade.mqh>

#define FIXED_LOTS 0.01

input group "=== Identity ==="

input long InpMagic = 715003;

input string InpComment = "V15_Var3";

input int InpMaxSpreadPoints = 400;

input group "=== Shared grid math ==="

input int InpMaxGridLayers = 20;

input double InpGridStepFrac = 0.001;

input double InpSlFrac = 0.976;

input int InpCooldownBars = 3;

input group "=== Variant3: HTF direction ==="

input ENUM_TIMEFRAMES InpHtf = PERIOD_H1;

input int InpHtfEmaFast = 50;

input int InpHtfEmaSlow = 200;

input bool InpExitOnHtfBear = true;

input bool InpBlockAddOnBear = true;

input group "=== Variant3: First-entry resonance (chart TF) ==="

input int InpKPeriod = 5;

input int InpDPeriod = 3;

input int InpSlowing = 3;

input double InpKdMax = 35.0; // KD below this + golden cross

input int InpBbPeriod = 20;

input double InpBbDev = 2.0;

input bool InpAllowKdOrBb = true; // OR logic: KD golden OR touch BB lower

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

CTrade trade;

CPositionInfo pos;

int g_hEmaFast = INVALID_HANDLE;

int g_hEmaSlow = INVALID_HANDLE;

int g_hStoch = INVALID_HANDLE;

int g_hBb = INVALID_HANDLE;

datetime g_lastBar = 0;

double g_initPrice = 0.0;

double g_gridStep = 0.0;

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

double TpMultByCount(const int count)

{

if(count <= 1) return 1.0020;

if(count == 2) return 1.0015;

if(count == 3) return 1.0012;

if(count == 4) return 1.0009;

if(count == 5) return 1.0006;

if(count == 6) return 1.0003;

return 1.0001;

}

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

bool SpreadOk()

{

return ((int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD) <= InpMaxSpreadPoints);

}

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

double NormLot(double lot)

{

double vmin = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);

double vmax = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);

double step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);

if(step <= 0.0) step = 0.01;

if(lot < vmin) lot = vmin;

if(lot > vmax) lot = vmax;

lot = MathFloor(lot / step + 1e-8) * step;

return NormalizeDouble(lot, 2);

}

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

int DigitsSym() { return (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS); }

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

bool HtfBull()

{

if(g_hEmaFast == INVALID_HANDLE || g_hEmaSlow == INVALID_HANDLE) return false;

double f[], s[];

ArraySetAsSeries(f, true);

ArraySetAsSeries(s, true);

if(CopyBuffer(g_hEmaFast, 0, 0, 3, f) < 3) return false;

if(CopyBuffer(g_hEmaSlow, 0, 0, 3, s) < 3) return false;

double c1 = iClose(_Symbol, InpHtf, 1);

return (c1 > f[1] && f[1] > s[1]);

}

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

bool HtfBearBreak()

{

if(g_hEmaFast == INVALID_HANDLE || g_hEmaSlow == INVALID_HANDLE) return false;

double f[], s[];

ArraySetAsSeries(f, true);

ArraySetAsSeries(s, true);

if(CopyBuffer(g_hEmaFast, 0, 0, 3, f) < 3) return false;

if(CopyBuffer(g_hEmaSlow, 0, 0, 3, s) < 3) return false;

double c1 = iClose(_Symbol, InpHtf, 1);

bool death = (f[2] >= s[2] && f[1] < s[1]);

bool below = (c1 < s[1]);

return (death || below);

}

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

bool FirstEntrySignal()

{

double k[], d[], bbLower[], bbMid[], bbUpper[];

ArraySetAsSeries(k, true);

ArraySetAsSeries(d, true);

ArraySetAsSeries(bbLower, true);

ArraySetAsSeries(bbMid, true);

ArraySetAsSeries(bbUpper, true);

if(CopyBuffer(g_hStoch, 0, 0, 3, k) < 3) return false;

if(CopyBuffer(g_hStoch, 1, 0, 3, d) < 3) return false;

// iBands: 0=BASE, 1=UPPER, 2=LOWER

if(CopyBuffer(g_hBb, 2, 0, 3, bbLower) < 3) return false;

double c1 = iClose(_Symbol, PERIOD_CURRENT, 1);

double l1 = iLow(_Symbol, PERIOD_CURRENT, 1);

bool kdGold = (k[2] <= d[2] && k[1] > d[1]);

bool kdOs = (k[1] <= InpKdMax || k[2] <= InpKdMax);

bool kdOk = (kdGold && kdOs);

bool touchBb = (l1 <= bbLower[1] || c1 <= bbLower[1]);

if(InpAllowKdOrBb)

return (kdOk || touchBb);

return (kdOk && touchBb);

}

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

int CountBuys(double &avg, double &lowest, datetime &lastT, datetime &oldest)

{

int n = 0;

double cost = 0.0, vol = 0.0;

avg = 0.0;

lowest = 0.0;

lastT = 0;

oldest = 0;

bool have = false;

for(int i = PositionsTotal() - 1; i >= 0; --i)

{

if(!pos.SelectByIndex(i)) continue;

if(pos.Symbol() != _Symbol || pos.Magic() != InpMagic) continue;

if(pos.PositionType() != POSITION_TYPE_BUY) continue;

n++;

double p = pos.PriceOpen();

double v = pos.Volume();

cost += p * v;

vol += v;

if(!have || p < lowest) { lowest = p; have = true; }

if(pos.Time() > lastT) lastT = pos.Time();

if(oldest == 0 || pos.Time() < oldest) oldest = pos.Time();

}

avg = (vol > 0.0 ? cost / vol : 0.0);

return n;

}

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

bool CloseAllBuys(const string reason)

{

bool ok = true;

for(int i = PositionsTotal() - 1; i >= 0; --i)

{

if(!pos.SelectByIndex(i)) continue;

if(pos.Symbol() != _Symbol || pos.Magic() != InpMagic) continue;

if(pos.PositionType() != POSITION_TYPE_BUY) continue;

if(!trade.PositionClose(pos.Ticket()))

{

ok = false;

Print(InpComment, " CLOSE FAIL ", reason, " ", trade.ResultRetcode());

}

}

if(ok)

{

Print(InpComment, " CLOSE_ALL ", reason);

g_initPrice = 0.0;

g_gridStep = 0.0;

}

return ok;

}

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

void SyncSl(const double slPrice)

{

int digits = DigitsSym();

double sl = NormalizeDouble(slPrice, digits);

long stops = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);

double minD = (double)stops * _Point;

double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);

if(sl >= bid - minD)

sl = NormalizeDouble(bid - MathMax(minD, 10 * _Point), digits);

for(int i = PositionsTotal() - 1; i >= 0; --i)

{

if(!pos.SelectByIndex(i)) continue;

if(pos.Symbol() != _Symbol || pos.Magic() != InpMagic) continue;

if(pos.PositionType() != POSITION_TYPE_BUY) continue;

if(MathAbs(pos.StopLoss() - sl) > _Point)

trade.PositionModify(pos.Ticket(), sl, 0.0);

}

}

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

bool OpenBuy(const bool isAdd)

{

if(!SpreadOk()) return false;

trade.SetExpertMagicNumber(InpMagic);

trade.SetDeviationInPoints(40);

trade.SetTypeFillingBySymbol(_Symbol);

double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);

if(!isAdd)

{

g_initPrice = ask;

g_gridStep = g_initPrice * InpGridStepFrac;

if(g_gridStep <= 0.0) g_gridStep = 10 * _Point;

}

double sl = NormalizeDouble(g_initPrice * InpSlFrac, DigitsSym());

bool ok = trade.Buy(NormLot(FIXED_LOTS), _Symbol, ask, sl, 0.0,

isAdd ? InpComment + "_G" : InpComment + "_0");

if(ok)

{

Print(InpComment, isAdd ? " GRID" : " OPEN0",

" ask=", ask, " init=", g_initPrice, " step=", g_gridStep);

SyncSl(g_initPrice * InpSlFrac);

}

else

Print(InpComment, " BUY FAIL ", trade.ResultRetcode(), " ",

trade.ResultRetcodeDescription());

return ok;

}

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

void RecoverInitFromPositions()

{

double hi = 0.0;

for(int i = PositionsTotal() - 1; i >= 0; --i)

{

if(!pos.SelectByIndex(i)) continue;

if(pos.Symbol() != _Symbol || pos.Magic() != InpMagic) continue;

if(pos.PositionType() != POSITION_TYPE_BUY) continue;

if(pos.PriceOpen() > hi) hi = pos.PriceOpen();

}

if(hi > 0.0)

{

g_initPrice = hi;

g_gridStep = g_initPrice * InpGridStepFrac;

}

}

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

int OnInit()

{

trade.SetExpertMagicNumber(InpMagic);

g_hEmaFast = iMA(_Symbol, InpHtf, InpHtfEmaFast, 0, MODE_EMA, PRICE_CLOSE);

g_hEmaSlow = iMA(_Symbol, InpHtf, InpHtfEmaSlow, 0, MODE_EMA, PRICE_CLOSE);

g_hStoch = iStochastic(_Symbol, PERIOD_CURRENT, InpKPeriod, InpDPeriod, InpSlowing,

MODE_SMA, STO_LOWHIGH);

g_hBb = iBands(_Symbol, PERIOD_CURRENT, InpBbPeriod, 0, InpBbDev, PRICE_CLOSE);

if(g_hEmaFast == INVALID_HANDLE || g_hEmaSlow == INVALID_HANDLE ||

g_hStoch == INVALID_HANDLE || g_hBb == INVALID_HANDLE)

return INIT_FAILED;

Print(InpComment, " V15_Variant_3 H1 bull + KD<=", InpKdMax,

" OR BB lower | step=", InpGridStepFrac, " sl=", InpSlFrac);

return INIT_SUCCEEDED;

}

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

void OnDeinit(const int reason)

{

if(g_hEmaFast != INVALID_HANDLE) IndicatorRelease(g_hEmaFast);

if(g_hEmaSlow != INVALID_HANDLE) IndicatorRelease(g_hEmaSlow);

if(g_hStoch != INVALID_HANDLE) IndicatorRelease(g_hStoch);

if(g_hBb != INVALID_HANDLE) IndicatorRelease(g_hBb);

}

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

void OnTick()

{

double avg = 0.0, lowest = 0.0;

datetime lastT = 0, oldest = 0;

int count = CountBuys(avg, lowest, lastT, oldest);

if(count == 0)

{

g_initPrice = 0.0;

g_gridStep = 0.0;

}

else if(g_initPrice <= 0.0)

RecoverInitFromPositions();

bool htfOk = HtfBull();

bool htfBreak = HtfBearBreak();

if(count > 0 && InpExitOnHtfBear && htfBreak)

{

CloseAllBuys("HTF_BEAR_BREAK");

return;

}

double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);

double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);

if(count > 0 && avg > 0.0 && g_initPrice > 0.0)

{

double slPrice = g_initPrice * InpSlFrac;

double tpPrice = avg * TpMultByCount(count);

SyncSl(slPrice);

if(bid <= slPrice)

{

CloseAllBuys("SL_0.976");

return;

}

if(bid >= tpPrice)

{

Print(InpComment, " TP count=", count, " avg=", avg);

CloseAllBuys("BASKET_TP");

return;

}

// adds: fixed grid only; still require HTF bull if enabled

bool allowAdd = true;

if(InpBlockAddOnBear && !htfOk) allowAdd = false;

if(allowAdd && count < InpMaxGridLayers && g_gridStep > 0.0)

{

int barsPassed = (lastT > 0 ? iBarShift(_Symbol, PERIOD_CURRENT, lastT) : 0);

if(barsPassed < 0) barsPassed = 0;

if(barsPassed >= InpCooldownBars && ask <= lowest - g_gridStep)

OpenBuy(true);

}

}

datetime t = iTime(_Symbol, PERIOD_CURRENT, 0);

if(t == 0 || t == g_lastBar) return;

g_lastBar = t;

if(count != 0) return;

if(!htfOk) return;

if(!FirstEntrySignal()) return;

OpenBuy(false);

}

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