FirstEA/TDI_Stoch_Classic.mq5

276 行
10 KiB
MQL5

//+------------------------------------------------------------------------+
//| TDI_Stoch_Classic.mq5 |
//| Copyright Ruben Works |
//| |
//+------------------------------------------------------------------------+
#property copyright "Ruben Works"
#property link ""
#property version "1.00"
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
//--- 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;
}