155 lines
5.2 KiB
MQL5
155 lines
5.2 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| TradeManager.mqh |
| |
//| Copyright 2025, MetaQuotes Ltd. |
| |
//| https://www.mql5.com |
| |
//+------------------------------------------------------------------+
| |
#property copyright "Copyright 2025, MetaQuotes Ltd."
| |
#property link "https://www.mql5.com"
| |
#property version "1.00"
| |
| |
#include "../Configs/EAConfig.mqh"
| |
#include "../Market/DataManager.mqh"
| |
#include "TradeExecutor.mqh"
| |
#include "../Events/Events/TradingEvents.mqh"
| |
| |
#include <Mql5Book\TrailingStops.mqh>
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
class TradeManager final: public IEventListener
| |
{
| |
private:
| |
EventBus* m_bus;
| |
ITradeExecutor* m_executor;
| |
CTrailing m_trail;
| |
EAConfig configs;
| |
CPositions pos;
| |
| |
SymbolConfig findSymbol(string symbol)
| |
{
| |
for(int i = 0; i < configs.tfConfigs.Size(); i++)
| |
{
| |
SymbolConfig data = configs.tfConfigs.At(i);
| |
| |
if(data.symbol == symbol)
| |
return data;
| |
}
| |
SymbolConfig t;
| |
return t;
| |
}
| |
| |
public:
| |
TradeManager() {}
| |
~TradeManager() {}
| |
| |
double GetPoint(string symbol) { return SymbolInfoDouble(symbol, SYMBOL_POINT); }
| |
void TrailingAndBreakeven(string symbol);
| |
| |
void Initialize(EventBus * bus, ITradeExecutor * executor, EAConfig & m_configs)
| |
{
| |
m_bus = bus;
| |
m_executor = executor;
| |
configs = m_configs;
| |
}
| |
| |
virtual void OnEvent(AbstractEvent * event) override
| |
{
| |
if(event.GetType() == EXECUTE_MARKET_ORDER)
| |
{
| |
ExecuteMarketOrderEvent* e = (ExecuteMarketOrderEvent*)event;
| |
MarketOrderRequest req;
| |
req.symbol = e.GetSymbolName();
| |
req.direction = e.GetDirection();
| |
req.volume = e.GetVolume();
| |
req.sl = e.GetSL();
| |
req.tp = e.GetTP();
| |
req.comment = e.GetComment();
| |
req.magic = configs.magicNumber;
| |
req.price = e.GetPrice();
| |
ulong ticket = m_executor.PlaceMarketOrder(req);
| |
if(ticket > 0)
| |
{
| |
| |
PositionOpenedEvent* dpos = new PositionOpenedEvent(ticket, req.symbol, req.direction, req.volume, req.price, req.sl, req.tp, TimeCurrent());
| |
m_bus.Push(dpos);
| |
}
| |
}
| |
else
| |
if(event.GetType() == EXECUTE_PENDING_ORDER)
| |
{
| |
ExecutePendingOrderEvent* pend = (ExecutePendingOrderEvent*)event;
| |
PendingOrderRequest req;
| |
req.symbol = pend.GetSymbolName();
| |
req.type = pend.GetOrderType();
| |
req.volume = pend.GetVolume();
| |
req.price = pend.GetPrice();
| |
req.stoplimit = pend.GetStopLimit();
| |
req.sl = pend.GetSL();
| |
req.tp = pend.GetTP();
| |
req.expiration = pend.GetExpiration();
| |
req.comment = pend.GetComment();
| |
req.magic = configs.magicNumber;
| |
| |
ulong ticket = m_executor.PlacePendingOrder(req);
| |
| |
| |
if(ticket > 0)
| |
{
| |
PendingOrderPlacedEvent* placed = new PendingOrderPlacedEvent(
| |
ticket, req.symbol, req.type, req.volume, req.price, req.sl, req.tp,
| |
req.expiration, req.comment);
| |
m_bus.Push(placed);
| |
}
| |
}
| |
else
| |
if(event.GetType() == NEW_BAR)
| |
{
| |
TrailingAndBreakeven(event.GetSymbolName());
| |
}
| |
}
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
void TradeManager::TrailingAndBreakeven(string symbol)
| |
{
| |
ulong tickets[];
| |
pos.GetTickets(configs.magicNumber, tickets);
| |
| |
//Print(symbol, ": ", ArraySize(tickets));
| |
SymbolConfig c = findSymbol(symbol);
| |
| |
for(int i = 0; i < ArraySize(tickets); i++)
| |
{
| |
if(c.rmConfigs.UseTrailingStop)
| |
m_trail.TrailingStop(tickets[i], c.rmConfigs.TrailingStop, c.rmConfigs.MinimumProfit, c.rmConfigs.Step);
| |
| |
if(c.rmConfigs.UseBreakEven)
| |
m_trail.BreakEven(tickets[i], c.rmConfigs.BreakEvenProfit, c.rmConfigs.LockProfit);
| |
| |
if(c.rmConfigs.UseAutoClose)
| |
{
| |
if(PositionSelectByTicket(tickets[i]))
| |
{
| |
long open_time = PositionGetInteger(POSITION_TIME);
| |
datetime current_time = TimeCurrent();
| |
| |
int bar_count = Bars(symbol, c.tradeTimeframe, open_time, current_time);
| |
// Print(symbol, ": ", bar_count);
| |
if(bar_count >= c.rmConfigs.tradeDuration)
| |
{
| |
Print(symbol, ":Close ", bar_count);
| |
if(m_executor.ClosePosition(tickets[i]))
| |
{
| |
Print( "Closed" );
| |
| |
}
| |
}
| |
}
| |
}
| |
| |
}
| |
}
| |
//+------------------------------------------------------------------+
|