615 righe
23 KiB
MQL5
615 righe
23 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| PositionManager.mqh |
|
||
|
|
//| Copyright 2025, EscapeEA |
|
||
|
|
//| https://www.escapeea.com |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
#property copyright "Copyright 2025, EscapeEA"
|
||
|
|
#property link "https://www.escapeea.com"
|
||
|
|
#property version "1.00"
|
||
|
|
#property strict
|
||
|
|
|
||
|
|
#include <Trade\PositionInfo.mqh>
|
||
|
|
#include <Trade\SymbolInfo.mqh>
|
||
|
|
#include <Trade\Trade.mqh>
|
||
|
|
#include "InputValidation.mqh"
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Position scaling profiles |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
enum ENUM_SCALING_PROFILE {
|
||
|
|
SCALING_NONE, // No scaling
|
||
|
|
SCALING_CONSERVATIVE, // Conservative scaling
|
||
|
|
SCALING_MODERATE, // Moderate scaling
|
||
|
|
SCALING_AGGRESSIVE // Aggressive scaling
|
||
|
|
};
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Exit profiles |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
enum ENUM_EXIT_PROFILE {
|
||
|
|
EXIT_AGGRESSIVE, // Aggressive exit (tighter stops)
|
||
|
|
EXIT_BALANCED, // Balanced exit
|
||
|
|
EXIT_CONSERVATIVE // Conservative exit (wider stops)
|
||
|
|
};
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Position Manager class |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
class CPositionManager {
|
||
|
|
private:
|
||
|
|
CTrade *m_trade; // Trade object
|
||
|
|
CSymbolInfo *m_symbol; // Symbol info
|
||
|
|
CPositionInfo m_position; // Position info
|
||
|
|
|
||
|
|
// Configuration
|
||
|
|
double m_slPoints; // Stop loss in points
|
||
|
|
double m_tpPoints; // Take profit in points
|
||
|
|
double m_trailingStop; // Trailing stop in points
|
||
|
|
double m_breakEven; // Break even level in points
|
||
|
|
|
||
|
|
// State
|
||
|
|
bool m_initialized; // Initialization flag
|
||
|
|
bool m_autoBreakEven; // Auto break-even flag
|
||
|
|
bool m_scaleIn; // Scale into positions flag
|
||
|
|
bool m_scaleOut; // Scale out of positions flag
|
||
|
|
|
||
|
|
// Advanced position management
|
||
|
|
double m_breakEvenAt; // Pips in profit to move to break-even
|
||
|
|
double m_scaleInAt; // Pips in drawdown to scale in
|
||
|
|
double m_scaleOutAt; // Pips in profit to scale out
|
||
|
|
double m_scaleInFactor; // Scale-in volume factor
|
||
|
|
double m_scaleOutFactor; // Scale-out volume factor
|
||
|
|
|
||
|
|
// Private methods
|
||
|
|
bool CheckTrailingStop();
|
||
|
|
bool CheckBreakEven();
|
||
|
|
|
||
|
|
public:
|
||
|
|
// Constructor/Destructor
|
||
|
|
CPositionManager();
|
||
|
|
~CPositionManager();
|
||
|
|
|
||
|
|
// Initialization
|
||
|
|
bool Initialize(CTrade *trade, CSymbolInfo *symbol,
|
||
|
|
double slPoints, double tpPoints,
|
||
|
|
double trailingStop = 0, double breakEven = 0);
|
||
|
|
|
||
|
|
// Position management
|
||
|
|
bool OpenPosition(ENUM_ORDER_TYPE type, double volume,
|
||
|
|
double price, double sl, double tp,
|
||
|
|
const string comment = "");
|
||
|
|
bool ClosePosition(ulong ticket, const string comment = "");
|
||
|
|
bool CloseAllPositions(const string comment = "");
|
||
|
|
bool ModifyPosition(ulong ticket, double sl, double tp);
|
||
|
|
|
||
|
|
// Advanced position management
|
||
|
|
bool SetScalingProfile(ENUM_SCALING_PROFILE profile);
|
||
|
|
bool SetExitProfile(ENUM_EXIT_PROFILE profile);
|
||
|
|
|
||
|
|
// Getters
|
||
|
|
bool IsInitialized() const { return m_initialized; }
|
||
|
|
double GetPositionSize(ulong ticket);
|
||
|
|
double GetPositionProfit(ulong ticket);
|
||
|
|
double GetPositionStopLoss(ulong ticket);
|
||
|
|
double GetPositionTakeProfit(ulong ticket);
|
||
|
|
|
||
|
|
// Utility
|
||
|
|
void Update();
|
||
|
|
|
||
|
|
// Advanced methods
|
||
|
|
bool ScaleInPosition(ulong ticket, double volume);
|
||
|
|
bool ScaleOutPosition(ulong ticket, double volume);
|
||
|
|
double GetPositionRisk(ulong ticket);
|
||
|
|
bool SetDynamicRisk(bool enable, double maxDailyDrawdown = 5.0,
|
||
|
|
double maxPositionRisk = 2.0, double maxPortfolioRisk = 20.0,
|
||
|
|
double riskDecay = 0.9);
|
||
|
|
|
||
|
|
// Position clustering
|
||
|
|
bool SetPositionClustering(bool enable, double clusterDistance = 20.0, int maxClusters = 3);
|
||
|
|
|
||
|
|
// Market regime detection
|
||
|
|
bool SetRegimeFilter(bool enable, double trendThreshold = 0.3);
|
||
|
|
|
||
|
|
// News event handling
|
||
|
|
bool SetNewsFilter(bool enable, int minImpact = 2, int minutesBefore = 30, int minutesAfter = 15);
|
||
|
|
|
||
|
|
// Volatility-based position sizing
|
||
|
|
bool SetVolatilitySizing(bool enable, int period = 14, double multiplier = 1.5, double maxRisk = 2.0);
|
||
|
|
|
||
|
|
// Correlation management
|
||
|
|
bool SetCorrelationFilter(bool enable, const string &symbols = "", double maxCorrelation = 0.7);
|
||
|
|
|
||
|
|
// Grid trading
|
||
|
|
bool SetGridTrading(bool enable, double gridStep = 20.0, int maxLevels = 5, double volumeMultiplier = 1.5);
|
||
|
|
|
||
|
|
// Machine learning integration
|
||
|
|
bool SetMLIntegration(bool enable, double confidenceThreshold = 0.7);
|
||
|
|
|
||
|
|
// Adaptive position sizing
|
||
|
|
bool SetAdaptiveSizing(bool enable, double winRate = 0.5, double profitFactor = 1.5);
|
||
|
|
|
||
|
|
// Advanced exit strategies
|
||
|
|
bool SetTrailingDrawdown(bool enable, double drawdownPercent = 30.0);
|
||
|
|
bool SetVolatilityExit(bool enable, double volatilityLevel = 2.0);
|
||
|
|
|
||
|
|
// Time-based exit
|
||
|
|
bool SetTimeExit(bool enable, int maxHoldBars = 50);
|
||
|
|
|
||
|
|
// Position monitoring
|
||
|
|
bool UpdatePositionMetrics(ulong ticket);
|
||
|
|
|
||
|
|
// Risk management
|
||
|
|
bool CheckDailyDrawdown();
|
||
|
|
bool CheckPortfolioRisk();
|
||
|
|
|
||
|
|
// Position analysis
|
||
|
|
double CalculatePositionScore(const string symbol, ENUM_ORDER_TYPE type);
|
||
|
|
double CalculateOptimalF(double winRate, double winLossRatio);
|
||
|
|
double CalculateKellyCriterion(double winRate, double winLossRatio);
|
||
|
|
|
||
|
|
// Position clustering
|
||
|
|
bool IsInCluster(ulong ticket, double distance = 20.0);
|
||
|
|
|
||
|
|
// Market regime detection
|
||
|
|
ENUM_MARKET_REGIME GetMarketRegime();
|
||
|
|
|
||
|
|
// News impact analysis
|
||
|
|
int GetNewsImpact();
|
||
|
|
|
||
|
|
// Volatility analysis
|
||
|
|
double GetCurrentVolatility();
|
||
|
|
|
||
|
|
// Correlation analysis
|
||
|
|
double GetPortfolioCorrelation(const string symbol);
|
||
|
|
|
||
|
|
// Machine learning
|
||
|
|
bool LoadMLModel(const string modelFile);
|
||
|
|
double GetMLPositionScore(const string symbol, ENUM_ORDER_TYPE type);
|
||
|
|
bool UpdateMLModel(const MqlRates &rates[], const double &features[]);
|
||
|
|
|
||
|
|
// Advanced position monitoring
|
||
|
|
bool CheckPositionHealth(ulong ticket);
|
||
|
|
bool CheckMarketConditions();
|
||
|
|
bool CheckPositionTiming(ulong ticket);
|
||
|
|
|
||
|
|
// Advanced position adjustments
|
||
|
|
bool HedgePosition(ulong ticket);
|
||
|
|
bool AverageDown(ulong ticket, double maxDrawdown = 10.0);
|
||
|
|
bool ScaleOutAtProfit(ulong ticket, double profitTarget = 30.0, double scalePercent = 50.0);
|
||
|
|
|
||
|
|
// Position analysis
|
||
|
|
double CalculatePositionValue(ulong ticket);
|
||
|
|
double CalculatePositionRiskReward(ulong ticket);
|
||
|
|
double CalculatePositionScore(ulong ticket);
|
||
|
|
|
||
|
|
// Advanced order types
|
||
|
|
bool PlaceBracketOrder(const string symbol, ENUM_ORDER_TYPE type, double volume,
|
||
|
|
double entryPrice, double sl, double tp,
|
||
|
|
double breakEvenAt = 0, double trailingStop = 0,
|
||
|
|
datetime expiration = 0, const string comment = "");
|
||
|
|
|
||
|
|
// Advanced position management
|
||
|
|
bool ScalePosition(ulong ticket, double newVolume);
|
||
|
|
bool ScalePositionByRisk(ulong ticket, double riskPercent);
|
||
|
|
bool ScalePositionByVolatility(ulong ticket, double volatilityMultiplier = 1.0);
|
||
|
|
|
||
|
|
// Position monitoring and adjustment
|
||
|
|
bool CheckAndAdjustPosition(ulong ticket);
|
||
|
|
bool MonitorAndManagePositions();
|
||
|
|
|
||
|
|
// Advanced risk management
|
||
|
|
bool SetRiskParameters(double maxRiskPerTrade, double maxDailyRisk, double maxDrawdown);
|
||
|
|
bool CheckRiskParameters();
|
||
|
|
|
||
|
|
// Position analysis and optimization
|
||
|
|
double CalculateOptimalPositionSize(double riskAmount, double stopLoss);
|
||
|
|
double CalculatePositionRisk(double entryPrice, double stopLoss, double lotSize);
|
||
|
|
double CalculatePositionValue(double entryPrice, double lotSize);
|
||
|
|
|
||
|
|
// Advanced position monitoring
|
||
|
|
bool CheckPositionHealth(ulong ticket, double maxDrawdown = 20.0);
|
||
|
|
bool CheckPositionTiming(ulong ticket, int maxBars = 50);
|
||
|
|
|
||
|
|
// Advanced position adjustments
|
||
|
|
bool TrailingStop(ulong ticket, double trailingStop);
|
||
|
|
bool MoveToBreakEven(ulong ticket, double breakEvenAt);
|
||
|
|
|
||
|
|
// Position analysis
|
||
|
|
double CalculatePositionRiskReward(ulong ticket, double entryPrice, double stopLoss, double takeProfit);
|
||
|
|
double CalculatePositionScore(ulong ticket, double winRate, double profitFactor);
|
||
|
|
|
||
|
|
// Advanced order management
|
||
|
|
bool PlaceOCOOrders(ulong ticket, double stopLoss, double takeProfit);
|
||
|
|
bool PlaceBracketOrder(ulong ticket, double stopLoss, double takeProfit,
|
||
|
|
double breakEvenAt = 0, double trailingStop = 0);
|
||
|
|
|
||
|
|
// Position monitoring and management
|
||
|
|
bool MonitorPosition(ulong ticket);
|
||
|
|
bool ManagePosition(ulong ticket);
|
||
|
|
|
||
|
|
// Advanced position management
|
||
|
|
bool ScaleInAtDrawdown(ulong ticket, double drawdownPercent, double scaleFactor = 1.0);
|
||
|
|
bool ScaleOutAtProfit(ulong ticket, double profitPercent, double scaleFactor = 0.5);
|
||
|
|
|
||
|
|
// Position analysis and optimization
|
||
|
|
double CalculateOptimalPositionSize(double accountBalance, double riskPercent,
|
||
|
|
double stopLoss, double contractSize);
|
||
|
|
double CalculatePositionRisk(double entryPrice, double stopLoss,
|
||
|
|
double lotSize, double contractSize);
|
||
|
|
|
||
|
|
// Advanced position monitoring
|
||
|
|
bool CheckPositionHealth(ulong ticket, double maxDrawdownPercent,
|
||
|
|
int maxBarsHeld, double minRiskReward);
|
||
|
|
|
||
|
|
// Advanced position adjustments
|
||
|
|
bool AdjustStopLoss(ulong ticket, double newStopLoss);
|
||
|
|
bool AdjustTakeProfit(ulong ticket, double newTakeProfit);
|
||
|
|
|
||
|
|
// Position analysis
|
||
|
|
double CalculatePositionValue(double entryPrice, double lotSize, double contractSize);
|
||
|
|
double CalculatePositionRiskReward(ulong ticket, double currentPrice);
|
||
|
|
};
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Constructor |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
CPositionManager::CPositionManager() :
|
||
|
|
m_trade(NULL),
|
||
|
|
m_symbol(NULL),
|
||
|
|
m_initialized(false),
|
||
|
|
m_slPoints(0.0),
|
||
|
|
m_tpPoints(0.0),
|
||
|
|
m_trailingStop(0.0),
|
||
|
|
m_breakEven(0.0),
|
||
|
|
m_autoBreakEven(false),
|
||
|
|
m_scaleIn(false),
|
||
|
|
m_scaleOut(false),
|
||
|
|
m_breakEvenAt(0.0),
|
||
|
|
m_scaleInAt(0.0),
|
||
|
|
m_scaleOutAt(0.0),
|
||
|
|
m_scaleInFactor(1.0),
|
||
|
|
m_scaleOutFactor(0.5)
|
||
|
|
{
|
||
|
|
// Initialize member variables in the initialization list
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Destructor |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
CPositionManager::~CPositionManager() {
|
||
|
|
// Cleanup if needed
|
||
|
|
if(m_trade != NULL) {
|
||
|
|
delete m_trade;
|
||
|
|
m_trade = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(m_symbol != NULL) {
|
||
|
|
delete m_symbol;
|
||
|
|
m_symbol = NULL;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Initialize the position manager |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
bool CPositionManager::Initialize(CTrade *trade, CSymbolInfo *symbol,
|
||
|
|
double slPoints, double tpPoints,
|
||
|
|
double trailingStop, double breakEven) {
|
||
|
|
// Validate inputs
|
||
|
|
if(trade == NULL || symbol == NULL) {
|
||
|
|
Print("Error: Invalid trade or symbol pointer");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(slPoints < 0 || tpPoints < 0 || trailingStop < 0 || breakEven < 0) {
|
||
|
|
Print("Error: Invalid parameters");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Store references
|
||
|
|
m_trade = trade;
|
||
|
|
m_symbol = symbol;
|
||
|
|
|
||
|
|
// Store parameters
|
||
|
|
m_slPoints = slPoints;
|
||
|
|
m_tpPoints = tpPoints;
|
||
|
|
m_trailingStop = trailingStop;
|
||
|
|
m_breakEven = breakEven;
|
||
|
|
|
||
|
|
m_initialized = true;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Open a new position |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
bool CPositionManager::OpenPosition(ENUM_ORDER_TYPE type, double volume,
|
||
|
|
double price, double sl, double tp,
|
||
|
|
const string comment) {
|
||
|
|
if(!m_initialized) {
|
||
|
|
Print("Error: Position manager not initialized");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate inputs
|
||
|
|
if(volume <= 0 || price <= 0) {
|
||
|
|
Print("Error: Invalid volume or price");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Execute the trade
|
||
|
|
if(type == ORDER_TYPE_BUY) {
|
||
|
|
return m_trade.Buy(volume, m_symbol.Name(), price, sl, tp, comment);
|
||
|
|
}
|
||
|
|
else if(type == ORDER_TYPE_SELL) {
|
||
|
|
return m_trade.Sell(volume, m_symbol.Name(), price, sl, tp, comment);
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Close a position by ticket |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
bool CPositionManager::ClosePosition(ulong ticket, const string comment) {
|
||
|
|
if(!m_initialized) {
|
||
|
|
Print("Error: Position manager not initialized");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Select the position
|
||
|
|
if(!m_position.SelectByTicket(ticket)) {
|
||
|
|
Print("Error selecting position ", ticket);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Close the position
|
||
|
|
return m_trade.PositionClose(ticket, m_position.Deviation(), comment);
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Close all open positions |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
bool CPositionManager::CloseAllPositions(const string comment) {
|
||
|
|
if(!m_initialized) {
|
||
|
|
Print("Error: Position manager not initialized");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool result = true;
|
||
|
|
int total = PositionsTotal();
|
||
|
|
|
||
|
|
for(int i = total - 1; i >= 0; i--) {
|
||
|
|
ulong ticket = PositionGetTicket(i);
|
||
|
|
if(ticket > 0) {
|
||
|
|
if(!ClosePosition(ticket, comment)) {
|
||
|
|
result = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Modify position stop loss and take profit |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
bool CPositionManager::ModifyPosition(ulong ticket, double sl, double tp) {
|
||
|
|
if(!m_initialized) {
|
||
|
|
Print("Error: Position manager not initialized");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Select the position
|
||
|
|
if(!m_position.SelectByTicket(ticket)) {
|
||
|
|
Print("Error selecting position ", ticket);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Modify the position
|
||
|
|
return m_trade.PositionModify(ticket, sl, tp);
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Set position scaling profile |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
bool CPositionManager::SetScalingProfile(ENUM_SCALING_PROFILE profile) {
|
||
|
|
switch(profile) {
|
||
|
|
case SCALING_AGGRESSIVE:
|
||
|
|
m_scaleInFactor = 1.5;
|
||
|
|
m_scaleOutFactor = 0.5;
|
||
|
|
m_scaleInAt = 20.0;
|
||
|
|
m_scaleOutAt = 30.0;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case SCALING_MODERATE:
|
||
|
|
m_scaleInFactor = 1.25;
|
||
|
|
m_scaleOutFactor = 0.75;
|
||
|
|
m_scaleInAt = 25.0;
|
||
|
|
m_scaleOutAt = 40.0;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case SCALING_CONSERVATIVE:
|
||
|
|
m_scaleInFactor = 1.1;
|
||
|
|
m_scaleOutFactor = 0.9;
|
||
|
|
m_scaleInAt = 30.0;
|
||
|
|
m_scaleOutAt = 50.0;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case SCALING_NONE:
|
||
|
|
default:
|
||
|
|
m_scaleIn = false;
|
||
|
|
m_scaleOut = false;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
m_scaleIn = true;
|
||
|
|
m_scaleOut = true;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Set exit profile |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
bool CPositionManager::SetExitProfile(ENUM_EXIT_PROFILE profile) {
|
||
|
|
switch(profile) {
|
||
|
|
case EXIT_AGGRESSIVE:
|
||
|
|
m_trailingStop = 20.0;
|
||
|
|
m_breakEvenAt = 15.0;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case EXIT_BALANCED:
|
||
|
|
m_trailingStop = 30.0;
|
||
|
|
m_breakEvenAt = 25.0;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case EXIT_CONSERVATIVE:
|
||
|
|
m_trailingStop = 50.0;
|
||
|
|
m_breakEvenAt = 40.0;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Get position size |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
double CPositionManager::GetPositionSize(ulong ticket) {
|
||
|
|
if(m_position.SelectByTicket(ticket)) {
|
||
|
|
return m_position.Volume();
|
||
|
|
}
|
||
|
|
return 0.0;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Get position profit |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
double CPositionManager::GetPositionProfit(ulong ticket) {
|
||
|
|
if(m_position.SelectByTicket(ticket)) {
|
||
|
|
return m_position.Profit();
|
||
|
|
}
|
||
|
|
return 0.0;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Get position stop loss level |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
double CPositionManager::GetPositionStopLoss(ulong ticket) {
|
||
|
|
if(m_position.SelectByTicket(ticket)) {
|
||
|
|
return m_position.StopLoss();
|
||
|
|
}
|
||
|
|
return 0.0;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Get position take profit level |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
double CPositionManager::GetPositionTakeProfit(ulong ticket) {
|
||
|
|
if(m_position.SelectByTicket(ticket)) {
|
||
|
|
return m_position.TakeProfit();
|
||
|
|
}
|
||
|
|
return 0.0;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Update position manager (call in OnTick) |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void CPositionManager::Update() {
|
||
|
|
if(!m_initialized) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Update trailing stops if enabled
|
||
|
|
if(m_trailingStop > 0) {
|
||
|
|
CheckTrailingStop();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Update break-even if enabled
|
||
|
|
if(m_breakEven > 0) {
|
||
|
|
CheckBreakEven();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Check and update trailing stop |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
bool CPositionManager::CheckTrailingStop() {
|
||
|
|
if(!m_initialized || m_trailingStop <= 0) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool result = true;
|
||
|
|
int total = PositionsTotal();
|
||
|
|
|
||
|
|
for(int i = 0; i < total; i++) {
|
||
|
|
ulong ticket = PositionGetTicket(i);
|
||
|
|
if(ticket > 0 && m_position.SelectByTicket(ticket)) {
|
||
|
|
double currentSl = m_position.StopLoss();
|
||
|
|
double currentPrice = (m_position.PositionType() == POSITION_TYPE_BUY) ?
|
||
|
|
m_position.PriceCurrent() : m_position.PriceOpen();
|
||
|
|
double newSl = 0.0;
|
||
|
|
|
||
|
|
if(m_position.PositionType() == POSITION_TYPE_BUY) {
|
||
|
|
newSl = m_symbol.Bid() - (m_trailingStop * m_symbol.Point());
|
||
|
|
if(newSl > currentSl && newSl < m_symbol.Bid()) {
|
||
|
|
if(!ModifyPosition(ticket, newSl, m_position.TakeProfit())) {
|
||
|
|
result = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if(m_position.PositionType() == POSITION_TYPE_SELL) {
|
||
|
|
newSl = m_symbol.Ask() + (m_trailingStop * m_symbol.Point());
|
||
|
|
if((newSl < currentSl || currentSl == 0) && newSl > m_symbol.Ask()) {
|
||
|
|
if(!ModifyPosition(ticket, newSl, m_position.TakeProfit())) {
|
||
|
|
result = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Check and update break-even level |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
bool CPositionManager::CheckBreakEven() {
|
||
|
|
if(!m_initialized || m_breakEven <= 0) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool result = true;
|
||
|
|
int total = PositionsTotal();
|
||
|
|
|
||
|
|
for(int i = 0; i < total; i++) {
|
||
|
|
ulong ticket = PositionGetTicket(i);
|
||
|
|
if(ticket > 0 && m_position.SelectByTicket(ticket)) {
|
||
|
|
double currentSl = m_position.StopLoss();
|
||
|
|
double openPrice = m_position.PriceOpen();
|
||
|
|
double currentPrice = (m_position.PositionType() == POSITION_TYPE_BUY) ?
|
||
|
|
m_position.PriceCurrent() : m_position.PriceOpen();
|
||
|
|
double pointsProfit = MathAbs(currentPrice - openPrice) / m_symbol.Point();
|
||
|
|
|
||
|
|
if(pointsProfit >= m_breakEven) {
|
||
|
|
if(m_position.PositionType() == POSITION_TYPE_BUY) {
|
||
|
|
if(currentSl < openPrice) {
|
||
|
|
if(!ModifyPosition(ticket, openPrice, m_position.TakeProfit())) {
|
||
|
|
result = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if(m_position.PositionType() == POSITION_TYPE_SELL) {
|
||
|
|
if(currentSl > openPrice || currentSl == 0) {
|
||
|
|
if(!ModifyPosition(ticket, openPrice, m_position.TakeProfit())) {
|
||
|
|
result = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|