//+------------------------------------------------------------------------+ //| TDI_Stoch_Classic.mq5 | //| Copyright Ruben Works | //| | //+------------------------------------------------------------------------+ #property copyright "Ruben Works" #property link "" #property version "1.00" #include #include //--- Input Parameters input group "Strategy Settings" input double InpLots = 0.1; // Lot Size input int InpStopLoss = 7500; // Stop Loss (Points, Safe Default) input int InpTakeProfit = 3000; // Take Profit (Points) input int InpMagic = 111222; // Magic Number input int InpTimeExitHours = 16; // Max Holding Time (Hours) input group "TDI Settings" input int InpRSI_Period = 13; // RSI Period input int InpGreen_Period = 2; // RSI Price Line (Green) input int InpRed_Period = 7; // Trade Signal Line (Red) input group "Filter Settings" input bool InpUseETV = false; // Easy Trend Visualizer (Sniper Mode) input group "Trailing Stop Settings" input bool InpUseTrailing = true; // Enable Trailing Stop input int InpTrailingStart = 500; // Start Trailing After Profit (Points) input int InpTrailingDist = 500; // Trailing Distance (Points) input int InpTrailingStep = 50; // Trailing Step (Points) //--- Global Objects CTrade m_trade; CPositionInfo m_position; //--- Indicator Handles int hRSI; // Base RSI int hTDI_Green; // SMA(2) of RSI int hTDI_Red; // SMA(7) of RSI int hStoch; // Stochastic // ETV Handles int hADX10; int hADX14; int hADX20; //--- Buffers double bufGreen[]; double bufRed[]; double bufStochK[]; double bufStochD[]; // ETV Buffers double bufADX10[], bufPlus10[], bufMinus10[]; double bufADX14[]; double bufADX20[]; //--- Time Management datetime lastBarTime = 0; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // 1. Initialize Trade Object m_trade.SetExpertMagicNumber(InpMagic); m_trade.SetMarginMode(); m_trade.SetTypeFillingBySymbol(Symbol()); // 2. Indicator Handles // --- TDI Construction --- hRSI = iRSI(Symbol(), Period(), InpRSI_Period, PRICE_CLOSE); if(hRSI == INVALID_HANDLE) { Print("Failed to create RSI handle"); return INIT_FAILED; } hTDI_Green = iMA(Symbol(), Period(), InpGreen_Period, 0, MODE_SMA, hRSI); if(hTDI_Green == INVALID_HANDLE) { Print("Failed to create TDI Green handle"); return INIT_FAILED; } hTDI_Red = iMA(Symbol(), Period(), InpRed_Period, 0, MODE_SMA, hRSI); if(hTDI_Red == INVALID_HANDLE) { Print("Failed to create TDI Red handle"); return INIT_FAILED; } // --- Stochastic --- hStoch = iStochastic(Symbol(), Period(), 5, 3, 3, MODE_SMA, STO_LOWHIGH); if(hStoch == INVALID_HANDLE) { Print("Failed to create Stoch handle"); return INIT_FAILED; } // --- ETV Handles --- hADX10 = iADX(Symbol(), Period(), 10); if(hADX10 == INVALID_HANDLE) { Print("Failed to create ADX 10"); return INIT_FAILED; } hADX14 = iADX(Symbol(), Period(), 14); if(hADX14 == INVALID_HANDLE) { Print("Failed to create ADX 14"); return INIT_FAILED; } hADX20 = iADX(Symbol(), Period(), 20); if(hADX20 == INVALID_HANDLE) { Print("Failed to create ADX 20"); return INIT_FAILED; } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { IndicatorRelease(hRSI); IndicatorRelease(hTDI_Green); IndicatorRelease(hTDI_Red); IndicatorRelease(hStoch); IndicatorRelease(hADX10); IndicatorRelease(hADX14); IndicatorRelease(hADX20); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // 1. Check For Time/Trailing Exits (Every Tick) CheckTimeExits(); if(InpUseTrailing) CheckTrailingStop(); // 2. Check for New Bar (Entry Logic) if(!IsNewBar()) return; // 3. Data Buffers Copy if(CopyBuffer(hTDI_Green, 0, 0, 3, bufGreen) < 3) return; if(CopyBuffer(hTDI_Red, 0, 0, 3, bufRed) < 3) return; if(CopyBuffer(hStoch, 0, 0, 3, bufStochK) < 3) return; if(CopyBuffer(hStoch, 1, 0, 3, bufStochD) < 3) return; ArraySetAsSeries(bufGreen, true); ArraySetAsSeries(bufRed, true); ArraySetAsSeries(bufStochK, true); ArraySetAsSeries(bufStochD, true); double close1 = iClose(Symbol(), Period(), 1); // --- SIGNAL LOGIC (Classic) --- // 1. TDI Cross UP (Green crosses Red) bool tdiCross = (bufGreen[1] > bufRed[1]) && (bufGreen[2] <= bufRed[2]); // 2. Stoch Cross UP (K crosses D) bool stochCross = (bufStochK[1] > bufStochD[1]) && (bufStochK[2] <= bufStochD[2]); // 3. ETV Filter bool etvOk = true; if(InpUseETV) { etvOk = (CheckETV() == 1); } // --- EXECUTION (Simple Market Buy) --- if(tdiCross && stochCross && etvOk) { double sl_price = close1 - (InpStopLoss * _Point); double tp_price = close1 + (InpTakeProfit * _Point); double ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK); sl_price = NormalizeDouble(sl_price, _Digits); tp_price = NormalizeDouble(tp_price, _Digits); m_trade.Buy(InpLots, Symbol(), ask, sl_price, tp_price, "TDI Classic"); } } //+------------------------------------------------------------------+ //| Check ETV (Easy Trend Visualizer) Logic | //| Returns: 1 (Bull), -1 (Bear), 0 (Flat) | //+------------------------------------------------------------------+ int CheckETV() { // Copy Buffers if(CopyBuffer(hADX10, MAIN_LINE, 0, 3, bufADX10) < 3) return 0; if(CopyBuffer(hADX14, MAIN_LINE, 0, 3, bufADX14) < 3) return 0; if(CopyBuffer(hADX20, MAIN_LINE, 0, 3, bufADX20) < 3) return 0; if(CopyBuffer(hADX10, PLUSDI_LINE, 0, 2, bufPlus10) < 2) return 0; if(CopyBuffer(hADX10, MINUSDI_LINE, 0, 2, bufMinus10) < 2) return 0; ArraySetAsSeries(bufADX10, true); ArraySetAsSeries(bufADX14, true); ArraySetAsSeries(bufADX20, true); ArraySetAsSeries(bufPlus10, true); ArraySetAsSeries(bufMinus10, true); // 1. Check Rising (Current [1] > Prev [2]) bool rising10 = bufADX10[1] > bufADX10[2]; bool rising14 = bufADX14[1] > bufADX14[2]; bool rising20 = bufADX20[1] > bufADX20[2]; // 2. Check Levels bool level10 = bufADX10[1] > 35; bool level14 = bufADX14[1] > 30; if(rising10 && rising14 && rising20 && level10 && level14) { // Trend Exists. Determine Direction. if(bufPlus10[1] > bufMinus10[1]) return 1; // Bullish if(bufPlus10[1] < bufMinus10[1]) return -1; // Bearish } return 0; // Flat } //+------------------------------------------------------------------+ //| Helper Functions | //+------------------------------------------------------------------+ bool IsNewBar() { datetime currTime = iTime(Symbol(), Period(), 0); if(currTime != lastBarTime) { lastBarTime = currTime; return true; } return false; } void CheckTimeExits() { for(int i = PositionsTotal() - 1; i >= 0; i--) { if(m_position.SelectByIndex(i)) { if(m_position.Symbol() == Symbol() && m_position.Magic() == InpMagic) { if((TimeCurrent() - m_position.Time()) > (InpTimeExitHours * 3600)) m_trade.PositionClose(m_position.Ticket()); } } } } void CheckTrailingStop() { for(int i = PositionsTotal() - 1; i >= 0; i--) { if(m_position.SelectByIndex(i)) { if(m_position.Symbol() == Symbol() && m_position.Magic() == InpMagic && m_position.PositionType() == POSITION_TYPE_BUY) { double currentPrice = SymbolInfoDouble(Symbol(), SYMBOL_BID); double openPrice = m_position.PriceOpen(); double profitPts = (currentPrice - openPrice) / SymbolInfoDouble(Symbol(), SYMBOL_POINT); if(profitPts > InpTrailingStart) { double newSL = currentPrice - (InpTrailingDist * SymbolInfoDouble(Symbol(), SYMBOL_POINT)); if(newSL > m_position.StopLoss() + (InpTrailingStep * SymbolInfoDouble(Symbol(), SYMBOL_POINT))) { m_trade.PositionModify(m_position.Ticket(), NormalizeDouble(newSL, _Digits), m_position.TakeProfit()); } } } } } } //+------------------------------------------------------------------+ //| OnTester: Custom Optimization Criterion | //| Returns: Recovery Factor (Net Profit / Max DD) | //+------------------------------------------------------------------+ double OnTester() { double netProfit = TesterStatistics(STAT_PROFIT); double maxDD = TesterStatistics(STAT_EQUITY_DD); // In Money // Avoid division by zero if(maxDD == 0.0) maxDD = 1.0; // If negative profit, return the profit itself (negative value) if(netProfit < 0) return netProfit; return netProfit / maxDD; }