167 行
6.8 KiB
MQL5
167 行
6.8 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| TestRefactor.mq5 – EA v OOP, zapouzdřené třídy |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
#property copyright "TestRefactor"
|
||
|
|
#property version "1.00"
|
||
|
|
#property strict
|
||
|
|
|
||
|
|
#include "Context.mqh"
|
||
|
|
#include "Logger.mqh"
|
||
|
|
#include "Position.mqh"
|
||
|
|
#include "Positions.mqh"
|
||
|
|
#include "ClosedPosition.mqh"
|
||
|
|
#include "ClosedPositions.mqh"
|
||
|
|
#include "SignalEngine.mqh"
|
||
|
|
#include <Trade/Trade.mqh>
|
||
|
|
#include "EquityDrawdown.mqh"
|
||
|
|
#include "TrailingStop.mqh"
|
||
|
|
#include "Grid.mqh"
|
||
|
|
#include "Dashboard.mqh"
|
||
|
|
|
||
|
|
//--- Inputy (pouze zde, do tříd jdou přes CContext)
|
||
|
|
input int InpFastMaPeriod = 5; // Perioda rychlé SMA – kratší MA pro detekci crossoveru
|
||
|
|
input int InpSlowMaPeriod = 15; // Perioda pomalé SMA – delší MA pro trend
|
||
|
|
input int InpRsiPeriod = 14; // Perioda RSI indikátoru
|
||
|
|
input double InpRsiOverbought = 70; // RSI horní hranice – signál BUY jen když RSI < tato hodnota
|
||
|
|
input double InpRsiOversold = 30; // RSI dolní hranice – signál SELL jen když RSI > tato hodnota
|
||
|
|
input double InpLotSize = 0.1; // Velikost lotu pro otevření pozic
|
||
|
|
input double InpTrailingTriggerUSD = 3.0; // Zisk v USD, od kterého se aktivuje trailing stop (Single režim)
|
||
|
|
input double InpTrailingDistanceUSD = 1.0; // Vzdálenost trailing stop od aktuálního zisku v USD
|
||
|
|
input double InpSmaMinDistancePoints = 0; // Min. vzdálenost SMA v bodech – signál jen když Fast-Slow >= tato hodnota (0 = vypnuto)
|
||
|
|
input int InpH1TrendMaPeriod = 50; // Perioda SMA na H1 – trend: close > MA = uptrend (0 = vypnuto)
|
||
|
|
input group "=== Ověření směru pozic (2 další timeframy) ==="
|
||
|
|
input ENUM_TIMEFRAMES InpTimeframe1 = PERIOD_H4; // TF1 – první timeframe pro filtrování otevření Grid pozic
|
||
|
|
input int InpTimeframe1MaPeriod = 20; // Perioda SMA na TF1 – BUY jen když close > MA (0 = vypnuto)
|
||
|
|
input ENUM_TIMEFRAMES InpTimeframe2 = PERIOD_D1; // TF2 – druhý timeframe pro filtrování otevření Grid pozic
|
||
|
|
input int InpTimeframe2MaPeriod = 50; // Perioda SMA na TF2 – oba TF musí souhlasit se směrem (0 = vypnuto)
|
||
|
|
input group "=== Obchodování ==="
|
||
|
|
input ENUM_TRADE_MODE InpTradeMode = TRADE_SINGLE; // Režim: Single (jedna pozice) nebo Grid (více úrovní)
|
||
|
|
input group "=== Grid ==="
|
||
|
|
input double InpGridDistancePoints = 50; // Vzdálenost mezi úrovněmi Gridu v bodech – nová pozice při pohybu ceny
|
||
|
|
input double InpGridTargetProfitUSD = 20.0; // Cílový zisk v USD – při dosažení se uzavře celý Grid
|
||
|
|
input int InpGridMaxLevels = 20; // Max. počet úrovní (pozic) v jednom směru
|
||
|
|
input group "=== Ostatní ==="
|
||
|
|
input double InpMaxEquityDrawdownPct = 10.0; // Max. povolený drawdown equity v % – při překročení uzavřít všechny pozice (jen Single)
|
||
|
|
input ENUM_EXIT_MODE InpExitMode = EXIT_BY_SL_TRAIL; // Režim uzavření: SL & Trailing nebo Opposite Crossover
|
||
|
|
|
||
|
|
//--- Globální objekty
|
||
|
|
CContext g_ctx;
|
||
|
|
CLogger g_log;
|
||
|
|
CPositions g_positions(_Symbol);
|
||
|
|
CSignalEngine g_signals;
|
||
|
|
CEquityDrawdown g_equityDD;
|
||
|
|
CTrailingStop g_trailing;
|
||
|
|
CGrid g_grid;
|
||
|
|
CDashboard g_dashboard;
|
||
|
|
CTrade g_trade;
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
int OnInit() {
|
||
|
|
g_ctx.SetFromInputs(
|
||
|
|
InpFastMaPeriod,
|
||
|
|
InpSlowMaPeriod,
|
||
|
|
InpRsiPeriod,
|
||
|
|
InpRsiOverbought,
|
||
|
|
InpRsiOversold,
|
||
|
|
InpLotSize,
|
||
|
|
InpTrailingTriggerUSD,
|
||
|
|
InpTrailingDistanceUSD,
|
||
|
|
InpSmaMinDistancePoints,
|
||
|
|
InpH1TrendMaPeriod,
|
||
|
|
InpTimeframe1,
|
||
|
|
InpTimeframe1MaPeriod,
|
||
|
|
InpTimeframe2,
|
||
|
|
InpTimeframe2MaPeriod,
|
||
|
|
InpTradeMode,
|
||
|
|
InpGridDistancePoints,
|
||
|
|
InpGridTargetProfitUSD,
|
||
|
|
InpMaxEquityDrawdownPct,
|
||
|
|
InpExitMode
|
||
|
|
);
|
||
|
|
g_ctx.SetGridMaxLevels(InpGridMaxLevels);
|
||
|
|
|
||
|
|
g_signals.SetSymbol(_Symbol);
|
||
|
|
g_signals.SetContext(g_ctx.Get());
|
||
|
|
g_signals.SetLogger(&g_log);
|
||
|
|
if(!g_signals.Init()) return INIT_FAILED;
|
||
|
|
|
||
|
|
g_equityDD.SetContext(g_ctx.Get());
|
||
|
|
g_equityDD.SetPositions(&g_positions);
|
||
|
|
g_equityDD.SetLogger(&g_log);
|
||
|
|
g_equityDD.SetTrade(&g_trade);
|
||
|
|
g_equityDD.SetSymbol(_Symbol);
|
||
|
|
|
||
|
|
g_trailing.SetContext(g_ctx.Get());
|
||
|
|
g_trailing.SetPositions(&g_positions);
|
||
|
|
g_trailing.SetTrade(&g_trade);
|
||
|
|
g_trailing.SetSymbol(_Symbol);
|
||
|
|
|
||
|
|
g_grid.SetContext(g_ctx.Get());
|
||
|
|
g_grid.SetPositions(&g_positions);
|
||
|
|
g_grid.SetLogger(&g_log);
|
||
|
|
g_grid.SetTrade(&g_trade);
|
||
|
|
g_grid.SetSymbol(_Symbol);
|
||
|
|
|
||
|
|
g_dashboard.SetContext(g_ctx.Get());
|
||
|
|
g_dashboard.SetPositions(&g_positions);
|
||
|
|
g_dashboard.SetSignalEngine(&g_signals);
|
||
|
|
g_dashboard.SetSymbol(_Symbol);
|
||
|
|
|
||
|
|
return INIT_SUCCEEDED;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void OnDeinit(const int reason) {
|
||
|
|
g_signals.Deinit();
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void OnTick() {
|
||
|
|
g_positions.Refresh();
|
||
|
|
|
||
|
|
g_equityDD.CheckAndClose();
|
||
|
|
g_grid.CheckProfitTargetAndClose();
|
||
|
|
g_trailing.Update();
|
||
|
|
|
||
|
|
if(g_signals.IsNewBar()) {
|
||
|
|
SSignalResult sig = g_signals.GetSignals();
|
||
|
|
if(!sig.ok) return;
|
||
|
|
|
||
|
|
SContext ctx = g_ctx.Get();
|
||
|
|
|
||
|
|
if(ctx.exitMode == EXIT_BY_OPPOSITE_SIGNAL && ctx.tradeMode == TRADE_SINGLE) {
|
||
|
|
ulong tickets[];
|
||
|
|
g_positions.GetTickets(tickets);
|
||
|
|
int n = ArraySize(tickets);
|
||
|
|
for(int i = 0; i < n; i++) {
|
||
|
|
if(!PositionSelectByTicket(tickets[i])) continue;
|
||
|
|
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
|
||
|
|
if(sig.buySignal && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
|
||
|
|
g_trade.PositionClose(tickets[i]);
|
||
|
|
if(sig.sellSignal && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
|
||
|
|
g_trade.PositionClose(tickets[i]);
|
||
|
|
}
|
||
|
|
g_positions.Refresh();
|
||
|
|
}
|
||
|
|
|
||
|
|
if(ctx.tradeMode == TRADE_SINGLE) {
|
||
|
|
if(sig.buySignal) {
|
||
|
|
g_log.Info("Fast MA > Slow MA & RSI < " + DoubleToString(ctx.rsiOverbought, 0));
|
||
|
|
g_trade.Buy(sig.volume, _Symbol, SymbolInfoDouble(_Symbol, SYMBOL_ASK), 0, 0, "Buy");
|
||
|
|
}
|
||
|
|
if(sig.sellSignal) {
|
||
|
|
g_log.Info("Fast MA < Slow MA & RSI > " + DoubleToString(ctx.rsiOversold, 0));
|
||
|
|
g_trade.Sell(sig.volume, _Symbol, SymbolInfoDouble(_Symbol, SYMBOL_BID), 0, 0, "Sell");
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
bool tfBuyValid = true, tfSellValid = true;
|
||
|
|
if(ctx.timeframe1MaPeriod > 0 || ctx.timeframe2MaPeriod > 0) {
|
||
|
|
tfBuyValid = g_signals.IsBuyDirectionValid();
|
||
|
|
tfSellValid = g_signals.IsSellDirectionValid();
|
||
|
|
}
|
||
|
|
g_grid.OnNewBar(sig.buySignal, sig.sellSignal, sig.volume, tfBuyValid, tfSellValid);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
g_dashboard.Update();
|
||
|
|
}
|