mql5/Experts/testRefactor2/testRefactor2.mq5

167 行
6.8 KiB
MQL5
Raw パーマリンク 通常表示 履歴

2026-02-01 21:39:33 +01:00
//+------------------------------------------------------------------+
//| 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();
}