72 Zeilen
2,7 KiB
MQL5
72 Zeilen
2,7 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| TrailingStop.mqh – trailing stop pro režim jedné pozice |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
#property copyright "TestRefactor"
|
||
|
|
#property strict
|
||
|
|
|
||
|
|
#ifndef __TRAILING_STOP_MQH__
|
||
|
|
#define __TRAILING_STOP_MQH__
|
||
|
|
|
||
|
|
#include "Context.mqh"
|
||
|
|
#include "Positions.mqh"
|
||
|
|
#include "Logger.mqh"
|
||
|
|
#include <Trade/Trade.mqh>
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| CTrailingStop – logika trailing stop uvnitř třídy |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
class CTrailingStop {
|
||
|
|
private:
|
||
|
|
SContext m_ctx;
|
||
|
|
CPositions *m_positions;
|
||
|
|
CTrade *m_trade;
|
||
|
|
string m_symbol;
|
||
|
|
|
||
|
|
public:
|
||
|
|
CTrailingStop() : m_positions(NULL), m_trade(NULL), m_symbol("") {}
|
||
|
|
|
||
|
|
void SetContext(const SContext &ctx) { m_ctx = ctx; }
|
||
|
|
void SetPositions(CPositions *pos) { m_positions = pos; }
|
||
|
|
void SetTrade(CTrade *trade) { m_trade = trade; }
|
||
|
|
void SetSymbol(string symbol) { m_symbol = symbol; }
|
||
|
|
|
||
|
|
void Update() {
|
||
|
|
if(m_ctx.tradeMode == TRADE_GRID || m_ctx.exitMode != EXIT_BY_SL_TRAIL) return;
|
||
|
|
if(!m_trade || !m_positions) return;
|
||
|
|
|
||
|
|
double tickValue = SymbolInfoDouble(m_symbol, SYMBOL_TRADE_TICK_VALUE);
|
||
|
|
double tickSize = SymbolInfoDouble(m_symbol, SYMBOL_TRADE_TICK_SIZE);
|
||
|
|
if(tickValue <= 0 || tickSize <= 0) return;
|
||
|
|
|
||
|
|
m_positions.Refresh();
|
||
|
|
ulong tickets[];
|
||
|
|
m_positions.GetTickets(tickets);
|
||
|
|
int n = ArraySize(tickets);
|
||
|
|
for(int i = 0; i < n; i++) {
|
||
|
|
if(!PositionSelectByTicket(tickets[i])) continue;
|
||
|
|
if(PositionGetString(POSITION_SYMBOL) != m_symbol) continue;
|
||
|
|
|
||
|
|
double profit = PositionGetDouble(POSITION_PROFIT);
|
||
|
|
if(profit < m_ctx.trailingTriggerUSD) continue;
|
||
|
|
|
||
|
|
ulong ticket = tickets[i];
|
||
|
|
double sl = PositionGetDouble(POSITION_SL);
|
||
|
|
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
||
|
|
double volume = PositionGetDouble(POSITION_VOLUME);
|
||
|
|
double gapUSD = m_ctx.trailingTriggerUSD - m_ctx.trailingDistanceUSD;
|
||
|
|
double targetProfitUSD = profit - gapUSD;
|
||
|
|
double priceDelta = (targetProfitUSD * tickSize) / (tickValue * volume);
|
||
|
|
double newSl = 0;
|
||
|
|
|
||
|
|
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
|
||
|
|
newSl = NormalizeDouble(openPrice + priceDelta, _Digits);
|
||
|
|
if(newSl > sl) m_trade.PositionModify(ticket, newSl, 0);
|
||
|
|
} else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {
|
||
|
|
newSl = NormalizeDouble(openPrice - priceDelta, _Digits);
|
||
|
|
if(newSl < sl || sl == 0) m_trade.PositionModify(ticket, newSl, 0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
#endif
|