update to my mt5 libs to include better comments
This commit is contained in:
+134
-135
@@ -1,24 +1,35 @@
|
||||
#include <Trade/Trade.mqh>
|
||||
#include <MyLibs/utils/AtrHandleManager.mqh>
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// GLOBALS
|
||||
// ---------------------------------------------------------------------
|
||||
CTrade trade;
|
||||
AtrHandleManager atr_manager;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// CLASS: AdjustPosition
|
||||
// ---------------------------------------------------------------------
|
||||
// Provides methods to manage stop-loss logic for runner trades.
|
||||
// Includes breakeven, trailing stop (fixed and ATR), and virtual TP SLs.
|
||||
// ---------------------------------------------------------------------
|
||||
class AdjustPosition {
|
||||
public:
|
||||
public:
|
||||
void set_breakeven_sl(string symbol, int runner_magic_no, double buffer_points = 5);
|
||||
void set_breakeven_if_profit_target_hit(string symbol, int runner_magic_no, double buffer_points = 5);
|
||||
void set_fixed_sl(string symbol, int runner_magic_no, double fixed_sl_price);
|
||||
void set_trailing_sl(string symbol, int runner_magic_no, double sl_offset_points = 5);
|
||||
void trailing_stop_atr(string symbol, int magic_number, ENUM_TIMEFRAMES tf = PERIOD_CURRENT, double activation_mult = 1.0,
|
||||
double trail_mult = 1.0, int atr_period = 14, bool use_bar_close = false);
|
||||
void trailing_stop_atr(string symbol, int magic_number, ENUM_TIMEFRAMES tf = PERIOD_CURRENT, double activation_mult = 1.0,
|
||||
double trail_mult = 1.0, int atr_period = 14, bool use_bar_close = false);
|
||||
|
||||
private:
|
||||
void set_breakeven_sl_for_ticket(string symbol, ulong ticket, long order_type, double entry_price, double current_sl, double current_tp, int digits, double buffer_price, bool remove_tp);
|
||||
private:
|
||||
void set_breakeven_sl_for_ticket(string symbol, ulong ticket, long order_type, double entry_price,
|
||||
double current_sl, double current_tp, int digits, double buffer_price, bool remove_tp);
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Sets SL to breakeven for all matching runner trades.
|
||||
// ---------------------------------------------------------------------
|
||||
void AdjustPosition::set_breakeven_sl(string symbol, int runner_magic_no, double buffer_points) {
|
||||
int digits = (int) SymbolInfoInteger(symbol, SYMBOL_DIGITS);
|
||||
double buffer_price = buffer_points * _Point;
|
||||
@@ -38,37 +49,33 @@ void AdjustPosition::set_breakeven_sl(string symbol, int runner_magic_no, double
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Check runner trades for virtual TP hits and set SL to breakeven if crossed.
|
||||
// Optimized to avoid unnecessary processing on every OnTimer()/OnTick() call.
|
||||
// ---------------------------------------------------------------------
|
||||
// Sets SL to breakeven if virtual TP (in comment) was hit.
|
||||
// ---------------------------------------------------------------------
|
||||
void AdjustPosition::set_breakeven_if_profit_target_hit(string symbol, int runner_magic_no, double buffer_points) {
|
||||
|
||||
// --- Get current bid/ask and symbol precision
|
||||
double ask = SymbolInfoDouble(symbol, SYMBOL_ASK);
|
||||
double bid = SymbolInfoDouble(symbol, SYMBOL_BID);
|
||||
int digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
|
||||
int digits = (int) SymbolInfoInteger(symbol, SYMBOL_DIGITS);
|
||||
double buffer_price = buffer_points * _Point;
|
||||
double price_margin = 50 * _Point; // avoid premature checking if far from TP
|
||||
double price_margin = 50 * _Point;
|
||||
|
||||
// --- Fast check: skip if no runner trades exist for this symbol
|
||||
bool has_runner = false;
|
||||
for (int i = PositionsTotal() - 1; i >= 0; i--) {
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if (!PositionSelectByTicket(ticket)) continue;
|
||||
if (PositionGetString(POSITION_SYMBOL) != symbol) continue;
|
||||
if ((int)PositionGetInteger(POSITION_MAGIC) == runner_magic_no) {
|
||||
if ((int) PositionGetInteger(POSITION_MAGIC) == runner_magic_no) {
|
||||
has_runner = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!has_runner) return;
|
||||
|
||||
// --- Loop through positions for breakeven SL
|
||||
for (int i = PositionsTotal() - 1; i >= 0; i--) {
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if (!PositionSelectByTicket(ticket)) continue;
|
||||
if (PositionGetString(POSITION_SYMBOL) != symbol) continue;
|
||||
if ((int)PositionGetInteger(POSITION_MAGIC) != runner_magic_no) continue;
|
||||
if ((int) PositionGetInteger(POSITION_MAGIC) != runner_magic_no) continue;
|
||||
|
||||
long order_type = PositionGetInteger(POSITION_TYPE);
|
||||
double entry = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
@@ -76,51 +83,135 @@ void AdjustPosition::set_breakeven_if_profit_target_hit(string symbol, int runne
|
||||
double tp = PositionGetDouble(POSITION_TP);
|
||||
string comment = PositionGetString(POSITION_COMMENT);
|
||||
|
||||
|
||||
// --- Parse virtual TP from comment: expected format "runner_tp:1.10500"
|
||||
double virtual_tp = 0.0;
|
||||
if (StringFind(comment, "runner_tp:") == 0) {
|
||||
string tp_str = StringSubstr(comment, StringLen("runner_tp:"));
|
||||
virtual_tp = StringToDouble(tp_str);
|
||||
}
|
||||
|
||||
if (virtual_tp <= 0.0) continue; // no valid virtual TP
|
||||
if (tp > 0.0) {
|
||||
if (virtual_tp <= 0.0) continue;
|
||||
if (tp > 0.0)
|
||||
PrintFormat("Warning: Runner trade on %s (ticket %d) has TP set: %.5f", symbol, ticket, tp);
|
||||
}
|
||||
|
||||
// --- Skip early if price not near virtual TP
|
||||
if (order_type == POSITION_TYPE_BUY && bid < virtual_tp - price_margin) continue;
|
||||
if (order_type == POSITION_TYPE_SELL && ask > virtual_tp + price_margin) continue;
|
||||
|
||||
// --- Check if virtual TP was hit
|
||||
bool tp_hit = false;
|
||||
if (order_type == POSITION_TYPE_BUY && bid >= virtual_tp) tp_hit = true;
|
||||
if (order_type == POSITION_TYPE_SELL && ask <= virtual_tp) tp_hit = true;
|
||||
bool tp_hit = (order_type == POSITION_TYPE_BUY && bid >= virtual_tp) ||
|
||||
(order_type == POSITION_TYPE_SELL && ask <= virtual_tp);
|
||||
if (!tp_hit) continue;
|
||||
|
||||
// Calculate expected breakeven SL
|
||||
double expected_sl = (order_type == POSITION_TYPE_BUY)
|
||||
? entry + buffer_price
|
||||
: entry - buffer_price;
|
||||
|
||||
// Skip if SL already set to breakeven
|
||||
if (NormalizeDouble(sl, digits) == NormalizeDouble(expected_sl, digits)) continue;
|
||||
|
||||
|
||||
// --- Set breakeven SL
|
||||
set_breakeven_sl_for_ticket(symbol, ticket, order_type, entry, sl, tp, digits, buffer_price, true);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// TRAILING STOP ATR LOGIC
|
||||
// Sets SL for a single trade to breakeven, optionally removes TP.
|
||||
// ---------------------------------------------------------------------
|
||||
// This function updates the stop-loss of runner trades based on ATR.
|
||||
// It only applies to trades with the given magic number and symbol.
|
||||
void AdjustPosition::set_breakeven_sl_for_ticket(string symbol, ulong ticket, long order_type, double entry_price,
|
||||
double current_sl, double current_tp, int digits,
|
||||
double buffer_price, bool remove_tp) {
|
||||
double breakeven_sl = (order_type == POSITION_TYPE_BUY)
|
||||
? entry_price + buffer_price
|
||||
: entry_price - buffer_price;
|
||||
|
||||
if ((order_type == POSITION_TYPE_BUY && current_sl >= breakeven_sl) ||
|
||||
(order_type == POSITION_TYPE_SELL && current_sl <= breakeven_sl)) return;
|
||||
|
||||
MqlTradeRequest request = {};
|
||||
MqlTradeResult result;
|
||||
|
||||
request.action = TRADE_ACTION_SLTP;
|
||||
request.symbol = symbol;
|
||||
request.position = ticket;
|
||||
request.sl = NormalizeDouble(breakeven_sl, digits);
|
||||
request.tp = remove_tp ? 0.0 : current_tp;
|
||||
request.magic = (int) PositionGetInteger(POSITION_MAGIC);
|
||||
|
||||
if (!OrderSend(request, result))
|
||||
Print("Failed to adjust runner: ", symbol, ". Error: ", result.retcode);
|
||||
else if (remove_tp)
|
||||
Print("Runner upgraded to trailing: SL at breakeven, TP removed for ", symbol);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Sets a fixed SL price for all runner trades.
|
||||
// ---------------------------------------------------------------------
|
||||
void AdjustPosition::set_fixed_sl(string symbol, int runner_magic_no, double fixed_sl_price) {
|
||||
for (int i = PositionsTotal() - 1; i >= 0; i--) {
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if (!PositionSelectByTicket(ticket)) continue;
|
||||
if (PositionGetString(POSITION_SYMBOL) != symbol) continue;
|
||||
if ((int) PositionGetInteger(POSITION_MAGIC) != runner_magic_no) continue;
|
||||
|
||||
double current_sl = PositionGetDouble(POSITION_SL);
|
||||
double current_tp = PositionGetDouble(POSITION_TP);
|
||||
if (current_sl == fixed_sl_price) continue;
|
||||
|
||||
MqlTradeRequest request = {};
|
||||
MqlTradeResult result;
|
||||
|
||||
request.action = TRADE_ACTION_SLTP;
|
||||
request.symbol = symbol;
|
||||
request.position = ticket;
|
||||
request.sl = fixed_sl_price;
|
||||
request.tp = current_tp;
|
||||
request.magic = runner_magic_no;
|
||||
|
||||
if (!OrderSend(request, result))
|
||||
Print("Failed to set fixed SL for runner on ", symbol, ". Error: ", result.retcode);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Applies a fixed-point trailing stop to runner trades.
|
||||
// ---------------------------------------------------------------------
|
||||
void AdjustPosition::set_trailing_sl(string symbol, int runner_magic_no, double sl_offset_points) {
|
||||
int digits = (int) SymbolInfoInteger(symbol, SYMBOL_DIGITS);
|
||||
double offset = sl_offset_points * _Point;
|
||||
|
||||
for (int i = PositionsTotal() - 1; i >= 0; i--) {
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if (!PositionSelectByTicket(ticket)) continue;
|
||||
if (PositionGetString(POSITION_SYMBOL) != symbol) continue;
|
||||
if ((int) PositionGetInteger(POSITION_MAGIC) != runner_magic_no) continue;
|
||||
|
||||
long type = PositionGetInteger(POSITION_TYPE);
|
||||
double current_sl = PositionGetDouble(POSITION_SL);
|
||||
double current_tp = PositionGetDouble(POSITION_TP);
|
||||
double price = (type == POSITION_TYPE_BUY)
|
||||
? SymbolInfoDouble(symbol, SYMBOL_BID)
|
||||
: SymbolInfoDouble(symbol, SYMBOL_ASK);
|
||||
|
||||
double sl = (type == POSITION_TYPE_BUY) ? price - offset : price + offset;
|
||||
if ((type == POSITION_TYPE_BUY && sl <= current_sl) ||
|
||||
(type == POSITION_TYPE_SELL && sl >= current_sl)) continue;
|
||||
|
||||
MqlTradeRequest request = {};
|
||||
MqlTradeResult result;
|
||||
|
||||
request.action = TRADE_ACTION_SLTP;
|
||||
request.symbol = symbol;
|
||||
request.position = ticket;
|
||||
request.sl = NormalizeDouble(sl, digits);
|
||||
request.tp = current_tp;
|
||||
request.magic = runner_magic_no;
|
||||
|
||||
if (!OrderSend(request, result))
|
||||
Print("Failed to update trailing SL for runner on ", symbol, ". Error: ", result.retcode);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Applies an ATR-based trailing stop to runner trades.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : The trading symbol.
|
||||
// - symbol : Trading symbol.
|
||||
// - _magic_number : Magic number to identify trades.
|
||||
// - tf : Timeframe used for ATR calculation.
|
||||
// - activation_mult: Multiplier to determine when to activate trailing.
|
||||
@@ -132,8 +223,8 @@ void AdjustPosition::set_breakeven_if_profit_target_hit(string symbol, int runne
|
||||
// - Trailing starts only after activation distance is reached.
|
||||
// - SL is only updated if it moves closer to price (i.e., improves).
|
||||
// ---------------------------------------------------------------------
|
||||
void AdjustPosition::trailing_stop_atr(string symbol, int _magic_number, ENUM_TIMEFRAMES tf, double activation_mult, double trail_mult, int atr_period, bool use_bar_close) {
|
||||
|
||||
void AdjustPosition::trailing_stop_atr(string symbol, int _magic_number, ENUM_TIMEFRAMES tf, double activation_mult,
|
||||
double trail_mult, int atr_period, bool use_bar_close) {
|
||||
double atr = atr_manager.get_atr_value(symbol, tf, atr_period);
|
||||
if (atr == EMPTY_VALUE) return;
|
||||
|
||||
@@ -151,16 +242,19 @@ void AdjustPosition::trailing_stop_atr(string symbol, int _magic_number, ENUM_TI
|
||||
double entry = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
double sl = PositionGetDouble(POSITION_SL);
|
||||
double price = use_bar_close ? iClose(symbol, tf, 1) : (type == POSITION_TYPE_BUY ? bid : ask);
|
||||
|
||||
double trail_distance = atr * trail_mult;
|
||||
double activation_distance = atr * activation_mult;
|
||||
|
||||
bool should_trail = (type == POSITION_TYPE_BUY && price >= entry + activation_distance) || (type == POSITION_TYPE_SELL && price <= entry - activation_distance);
|
||||
bool should_trail = (type == POSITION_TYPE_BUY && price >= entry + activation_distance) ||
|
||||
(type == POSITION_TYPE_SELL && price <= entry - activation_distance);
|
||||
if (!should_trail) continue;
|
||||
|
||||
double new_sl = (type == POSITION_TYPE_BUY) ? price - trail_distance : price + trail_distance;
|
||||
new_sl = NormalizeDouble(new_sl, digits);
|
||||
|
||||
if ((type == POSITION_TYPE_BUY && sl >= new_sl) || (type == POSITION_TYPE_SELL && sl <= new_sl)) continue;
|
||||
if ((type == POSITION_TYPE_BUY && sl >= new_sl) ||
|
||||
(type == POSITION_TYPE_SELL && sl <= new_sl)) continue;
|
||||
|
||||
if (!trade.PositionModify(ticket, new_sl, PositionGetDouble(POSITION_TP)))
|
||||
PrintFormat("Trailing SL update failed for %s ticket=%d", symbol, ticket);
|
||||
@@ -168,98 +262,3 @@ void AdjustPosition::trailing_stop_atr(string symbol, int _magic_number, ENUM_TI
|
||||
PrintFormat("Trailing SL updated: %s ticket=%d new SL=%.5f", symbol, ticket, new_sl);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
void AdjustPosition::set_breakeven_sl_for_ticket(string symbol, ulong ticket, long order_type, double entry_price, double current_sl,
|
||||
double current_tp, int digits, double buffer_price, bool remove_tp) {
|
||||
double breakeven_sl = (order_type == POSITION_TYPE_BUY) ? entry_price + buffer_price : entry_price - buffer_price;
|
||||
|
||||
if ((order_type == POSITION_TYPE_BUY && current_sl >= breakeven_sl) || (order_type == POSITION_TYPE_SELL && current_sl <= breakeven_sl))
|
||||
return;
|
||||
|
||||
MqlTradeRequest request = {};
|
||||
MqlTradeResult result;
|
||||
|
||||
request.action = TRADE_ACTION_SLTP;
|
||||
request.symbol = symbol;
|
||||
request.position = ticket;
|
||||
request.sl = NormalizeDouble(breakeven_sl, digits);
|
||||
request.tp = remove_tp ? 0.0 : current_tp;
|
||||
request.magic = (int) PositionGetInteger(POSITION_MAGIC);
|
||||
|
||||
if (!OrderSend(request, result)) {
|
||||
Print("Failed to adjust runner: ", symbol, ". Error: ", result.retcode);
|
||||
} else if (remove_tp) {
|
||||
Print("Runner upgraded to trailing: SL at breakeven, TP removed for ", symbol);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
void AdjustPosition::set_fixed_sl(string symbol, int runner_magic_no, double fixed_sl_price) {
|
||||
for (int i = PositionsTotal() - 1; i >= 0; i--) {
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if (!PositionSelectByTicket(ticket)) continue;
|
||||
if (PositionGetString(POSITION_SYMBOL) != symbol) continue;
|
||||
if ((int) PositionGetInteger(POSITION_MAGIC) != runner_magic_no) continue;
|
||||
|
||||
double current_sl = PositionGetDouble(POSITION_SL);
|
||||
double current_tp = PositionGetDouble(POSITION_TP);
|
||||
|
||||
if (current_sl == fixed_sl_price) continue;
|
||||
|
||||
MqlTradeRequest request = {};
|
||||
MqlTradeResult result;
|
||||
|
||||
request.action = TRADE_ACTION_SLTP;
|
||||
request.symbol = symbol;
|
||||
request.position = ticket;
|
||||
request.sl = fixed_sl_price;
|
||||
request.tp = current_tp;
|
||||
request.magic = runner_magic_no;
|
||||
|
||||
if (!OrderSend(request, result)) {
|
||||
Print("Failed to set fixed SL for runner on ", symbol, ". Error: ", result.retcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
void AdjustPosition::set_trailing_sl(string symbol, int runner_magic_no, double sl_offset_points) {
|
||||
int digits = (int) SymbolInfoInteger(symbol, SYMBOL_DIGITS);
|
||||
double price = 0;
|
||||
double sl = 0;
|
||||
double offset = sl_offset_points * _Point;
|
||||
|
||||
for (int i = PositionsTotal() - 1; i >= 0; i--) {
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if (!PositionSelectByTicket(ticket)) continue;
|
||||
if (PositionGetString(POSITION_SYMBOL) != symbol) continue;
|
||||
if ((int) PositionGetInteger(POSITION_MAGIC) != runner_magic_no) continue;
|
||||
|
||||
long type = PositionGetInteger(POSITION_TYPE);
|
||||
double current_sl = PositionGetDouble(POSITION_SL);
|
||||
double current_tp = PositionGetDouble(POSITION_TP);
|
||||
|
||||
price = (type == POSITION_TYPE_BUY) ? SymbolInfoDouble(symbol, SYMBOL_BID) : SymbolInfoDouble(symbol, SYMBOL_ASK);
|
||||
|
||||
sl = (type == POSITION_TYPE_BUY) ? price - offset : price + offset;
|
||||
|
||||
if ((type == POSITION_TYPE_BUY && sl <= current_sl) || (type == POSITION_TYPE_SELL && sl >= current_sl)) continue;
|
||||
|
||||
MqlTradeRequest request = {};
|
||||
MqlTradeResult result;
|
||||
|
||||
request.action = TRADE_ACTION_SLTP;
|
||||
request.symbol = symbol;
|
||||
request.position = ticket;
|
||||
request.sl = NormalizeDouble(sl, digits);
|
||||
request.tp = current_tp;
|
||||
request.magic = runner_magic_no;
|
||||
|
||||
if (!OrderSend(request, result)) {
|
||||
Print("Failed to update trailing SL for runner on ", symbol, ". Error: ", result.retcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
#include <MyLibs/Utils/AtrHandleManager.mqh>
|
||||
#include <Trade/Trade.mqh>
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// CLASS: CalculatePositionData
|
||||
// ---------------------------------------------------------------------
|
||||
// Provides core logic for computing stop loss, take profit, lot size,
|
||||
// and trading costs based on symbol, price, and risk parameters.
|
||||
// ---------------------------------------------------------------------
|
||||
class CalculatePositionData : public CObject {
|
||||
protected:
|
||||
CTrade trade;
|
||||
@@ -20,8 +26,20 @@ public:
|
||||
double calculate_trading_cost(string symbol, ulong ticket);
|
||||
};
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Calculates stop loss based on selected method.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Symbol for the trade.
|
||||
// - price : Entry price.
|
||||
// - order_side: 1 = Buy, 2 = Sell.
|
||||
// - mode_sl : SL method ("NO_STOPLOSS", "SL_FIXED_PIPS", etc).
|
||||
// - sl_var : SL parameter (pips, %, ATR multiplier, or absolute).
|
||||
// - atr_tf : Timeframe for ATR.
|
||||
//
|
||||
// Returns:
|
||||
// - Calculated SL price, or 0 if invalid.
|
||||
// ---------------------------------------------------------------------
|
||||
double CalculatePositionData::calculate_stoploss(string symbol, double price, int order_side, string mode_sl, double sl_var, ENUM_TIMEFRAMES atr_tf) {
|
||||
double sl = 0;
|
||||
|
||||
@@ -55,8 +73,21 @@ double CalculatePositionData::calculate_stoploss(string symbol, double price, in
|
||||
return sl;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Calculates take profit based on selected method.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Symbol for the trade.
|
||||
// - price : Entry price.
|
||||
// - stoploss : SL value (used in TP/SL ratio mode).
|
||||
// - order_side: 1 = Buy, -1 = Sell.
|
||||
// - mode_tp : TP method ("NO_TAKE_PROFIT", "TP_FIXED_PIPS", etc).
|
||||
// - tp_var : TP parameter (pips, %, ATR multiplier, SL multiple).
|
||||
// - atr_tf : Timeframe for ATR.
|
||||
//
|
||||
// Returns:
|
||||
// - Calculated TP price, or 0 if invalid.
|
||||
// ---------------------------------------------------------------------
|
||||
double CalculatePositionData::calculate_take_profit(string symbol, double price, double stoploss, int order_side, string mode_tp, double tp_var, ENUM_TIMEFRAMES atr_tf) {
|
||||
double tp = 0;
|
||||
|
||||
@@ -96,8 +127,19 @@ double CalculatePositionData::calculate_take_profit(string symbol, double price,
|
||||
return tp;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Calculates lot size based on selected lot mode.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Symbol for the trade.
|
||||
// - sl_distance: SL distance in points.
|
||||
// - price : Current price.
|
||||
// - mode_lot : Lot mode ("LOT_MODE_FIXED", "LOT_MODE_PCT_RISK", etc).
|
||||
// - lot_var : Value for lot calculation.
|
||||
//
|
||||
// Returns:
|
||||
// - Computed lot size (rounded and validated).
|
||||
// ---------------------------------------------------------------------
|
||||
double CalculatePositionData::calculate_lots(string symbol, double sl_distance, double price, string mode_lot, double lot_var) {
|
||||
double lots = 0;
|
||||
double tick_size = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
|
||||
@@ -125,8 +167,16 @@ double CalculatePositionData::calculate_lots(string symbol, double sl_distance,
|
||||
return lots;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Validates and adjusts lot size to symbol constraints.
|
||||
//
|
||||
// Parameters:
|
||||
// - lots : Input/output lot size.
|
||||
// - symbol : Trading symbol.
|
||||
//
|
||||
// Returns:
|
||||
// - true if lots are valid after correction.
|
||||
// ---------------------------------------------------------------------
|
||||
bool CalculatePositionData::check_lots(double& lots, string symbol) {
|
||||
double min = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
|
||||
double max = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
|
||||
@@ -146,8 +196,17 @@ bool CalculatePositionData::check_lots(double& lots, string symbol) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Normalizes price to the nearest valid tick size.
|
||||
//
|
||||
// Parameters:
|
||||
// - price : Raw price.
|
||||
// - normalizedPrice: Output normalized price.
|
||||
// - symbol : Trading symbol.
|
||||
//
|
||||
// Returns:
|
||||
// - true if successful, false if tick size lookup failed.
|
||||
// ---------------------------------------------------------------------
|
||||
bool CalculatePositionData::normalise_price(double price, double& normalizedPrice, string symbol) {
|
||||
double tick_size;
|
||||
if (!SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE, tick_size)) {
|
||||
@@ -159,17 +218,3 @@ bool CalculatePositionData::normalise_price(double price, double& normalizedPric
|
||||
normalizedPrice = NormalizeDouble(MathRound(price / tick_size) * tick_size, digits);
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
// double CalculatePositionData::calculate_trading_cost(string symbol, ulong ticket) {
|
||||
// position.SelectByTicket(ticket);
|
||||
|
||||
// double swap = PositionGetDouble(POSITION_SWAP);
|
||||
// double commission = PositionGetDouble(POSITION_COMMISSION);
|
||||
// double tick_size = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
|
||||
// double tick_value = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
|
||||
// double lots = PositionGetDouble(POSITION_VOLUME);
|
||||
|
||||
// return -1.0 * ((commission + swap) / tick_value * tick_size / lots);
|
||||
// }
|
||||
|
||||
+123
-1
@@ -28,9 +28,19 @@ public:
|
||||
|
||||
bool open_runner_sell_order_with_virtual_tp(string symbol, bool condition, ENUM_TIMEFRAMES atr_period, string _sl_mode, double sl_var,
|
||||
string _tp_mode, double tp_var, string _lot_mode, double lot_var, long _magic_number);
|
||||
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Counts open positions by symbol, side, and magic number.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Symbol to check.
|
||||
// - order_side : 1 = Buy, 2 = Sell, 0 = Any.
|
||||
// - _magic_number : Magic number to filter.
|
||||
//
|
||||
// Returns:
|
||||
// - Number of matching open positions.
|
||||
// ---------------------------------------------------------------------
|
||||
int EntryOrders::count_open_positions(string symbol, int order_side, long _magic_number) {
|
||||
int count = 0;
|
||||
for (int i = PositionsTotal() - 1; i >= 0; i--) {
|
||||
@@ -45,6 +55,24 @@ int EntryOrders::count_open_positions(string symbol, int order_side, long _magic
|
||||
return count;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Opens a market BUY position.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Symbol to trade.
|
||||
// - condition : If false, trade will not execute.
|
||||
// - atr_period : Timeframe for ATR-based SL/TP.
|
||||
// - _sl_mode : SL calculation method.
|
||||
// - sl_var : SL variable (e.g., pips or ATR multiplier).
|
||||
// - _tp_mode : TP calculation method.
|
||||
// - tp_var : TP variable.
|
||||
// - _lot_mode : Lot calculation method.
|
||||
// - lot_var : Lot sizing variable.
|
||||
// - _magic_number : Magic number for trade.
|
||||
//
|
||||
// Returns:
|
||||
// - True if trade was placed successfully.
|
||||
// ---------------------------------------------------------------------
|
||||
bool EntryOrders::open_buy_orders(string symbol, bool condition, ENUM_TIMEFRAMES atr_period, string _sl_mode, double sl_var,
|
||||
string _tp_mode, double tp_var, string _lot_mode, double lot_var, long _magic_number) {
|
||||
if (!condition) return false;
|
||||
@@ -68,6 +96,24 @@ bool EntryOrders::open_buy_orders(string symbol, bool condition, ENUM_TIMEFRAMES
|
||||
return result;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Opens a market SELL position.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Symbol to trade.
|
||||
// - condition : If false, trade will not execute.
|
||||
// - atr_period : Timeframe for ATR-based SL/TP.
|
||||
// - _sl_mode : SL calculation method.
|
||||
// - sl_var : SL variable (e.g., pips or ATR multiplier).
|
||||
// - _tp_mode : TP calculation method.
|
||||
// - tp_var : TP variable.
|
||||
// - _lot_mode : Lot calculation method.
|
||||
// - lot_var : Lot sizing variable.
|
||||
// - _magic_number : Magic number for trade.
|
||||
//
|
||||
// Returns:
|
||||
// - True if trade was placed successfully.
|
||||
// ---------------------------------------------------------------------
|
||||
bool EntryOrders::open_sell_orders(string symbol, bool condition, ENUM_TIMEFRAMES atr_period, string _sl_mode, double sl_var,
|
||||
string _tp_mode, double tp_var, string _lot_mode, double lot_var, long _magic_number) {
|
||||
if (!condition) return false;
|
||||
@@ -91,6 +137,26 @@ bool EntryOrders::open_sell_orders(string symbol, bool condition, ENUM_TIMEFRAME
|
||||
return result;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Opens a pending BUY STOP order.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Symbol to trade.
|
||||
// - condition : If false, order will not be placed.
|
||||
// - entry_price : Trigger price for Buy Stop.
|
||||
// - expiration : Expiration time for pending order.
|
||||
// - atr_period : Timeframe for ATR-based SL/TP.
|
||||
// - _sl_mode : SL calculation method.
|
||||
// - sl_var : SL variable.
|
||||
// - _tp_mode : TP calculation method.
|
||||
// - tp_var : TP variable.
|
||||
// - _lot_mode : Lot calculation method.
|
||||
// - lot_var : Lot sizing variable.
|
||||
// - _magic_number : Magic number for order.
|
||||
//
|
||||
// Returns:
|
||||
// - True if order was placed successfully.
|
||||
// ---------------------------------------------------------------------
|
||||
bool EntryOrders::open_buy_stop_order(string symbol, bool condition, double entry_price, datetime expiration, ENUM_TIMEFRAMES atr_period,
|
||||
string _sl_mode, double sl_var, string _tp_mode, double tp_var, string _lot_mode, double lot_var,
|
||||
long _magic_number) {
|
||||
@@ -114,6 +180,26 @@ bool EntryOrders::open_buy_stop_order(string symbol, bool condition, double entr
|
||||
return result;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Opens a pending SELL STOP order.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Symbol to trade.
|
||||
// - condition : If false, order will not be placed.
|
||||
// - entry_price : Trigger price for Sell Stop.
|
||||
// - expiration : Expiration time for pending order.
|
||||
// - atr_period : Timeframe for ATR-based SL/TP.
|
||||
// - _sl_mode : SL calculation method.
|
||||
// - sl_var : SL variable.
|
||||
// - _tp_mode : TP calculation method.
|
||||
// - tp_var : TP variable.
|
||||
// - _lot_mode : Lot calculation method.
|
||||
// - lot_var : Lot sizing variable.
|
||||
// - _magic_number : Magic number for order.
|
||||
//
|
||||
// Returns:
|
||||
// - True if order was placed successfully.
|
||||
// ---------------------------------------------------------------------
|
||||
bool EntryOrders::open_sell_stop_order(string symbol, bool condition, double entry_price, datetime expiration, ENUM_TIMEFRAMES atr_period,
|
||||
string _sl_mode, double sl_var, string _tp_mode, double tp_var, string _lot_mode, double lot_var,
|
||||
long _magic_number) {
|
||||
@@ -137,6 +223,24 @@ bool EntryOrders::open_sell_stop_order(string symbol, bool condition, double ent
|
||||
return result;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Opens a market BUY runner with virtual TP in comment.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Symbol to trade.
|
||||
// - condition : If false, trade will not execute.
|
||||
// - atr_period : Timeframe for ATR-based SL.
|
||||
// - _sl_mode : SL calculation method.
|
||||
// - sl_var : SL variable.
|
||||
// - _tp_mode : TP calculation method.
|
||||
// - tp_var : TP variable (used for virtual TP).
|
||||
// - _lot_mode : Lot calculation method.
|
||||
// - lot_var : Lot sizing variable.
|
||||
// - _magic_number : Magic number for trade.
|
||||
//
|
||||
// Returns:
|
||||
// - True if trade was placed successfully.
|
||||
// ---------------------------------------------------------------------
|
||||
bool EntryOrders::open_runner_buy_order_with_virtual_tp(string symbol, bool condition, ENUM_TIMEFRAMES atr_period, string _sl_mode,
|
||||
double sl_var, string _tp_mode, double tp_var, string _lot_mode, double lot_var,
|
||||
long _magic_number) {
|
||||
@@ -161,6 +265,24 @@ bool EntryOrders::open_runner_buy_order_with_virtual_tp(string symbol, bool cond
|
||||
return result;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Opens a market SELL runner with virtual TP in comment.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Symbol to trade.
|
||||
// - condition : If false, trade will not execute.
|
||||
// - atr_period : Timeframe for ATR-based SL.
|
||||
// - _sl_mode : SL calculation method.
|
||||
// - sl_var : SL variable.
|
||||
// - _tp_mode : TP calculation method.
|
||||
// - tp_var : TP variable (used for virtual TP).
|
||||
// - _lot_mode : Lot calculation method.
|
||||
// - lot_var : Lot sizing variable.
|
||||
// - _magic_number : Magic number for trade.
|
||||
//
|
||||
// Returns:
|
||||
// - True if trade was placed successfully.
|
||||
// ---------------------------------------------------------------------
|
||||
bool EntryOrders::open_runner_sell_order_with_virtual_tp(string symbol, bool condition, ENUM_TIMEFRAMES atr_period, string _sl_mode,
|
||||
double sl_var, string _tp_mode, double tp_var, string _lot_mode, double lot_var,
|
||||
long _magic_number) {
|
||||
|
||||
+66
-4
@@ -3,7 +3,7 @@
|
||||
#include <Trade/Trade.mqh>
|
||||
|
||||
class ExitOrders {
|
||||
protected:
|
||||
protected:
|
||||
CTrade trade;
|
||||
TimeZones tz;
|
||||
CalculatePositionData calc;
|
||||
@@ -12,15 +12,27 @@ class ExitOrders {
|
||||
long position_open_time;
|
||||
long first_allowed_close_time;
|
||||
|
||||
public:
|
||||
public:
|
||||
bool close_buy_orders(string symbol, bool condition, int close_bars, ENUM_TIMEFRAMES close_bar_period, long _magic_number);
|
||||
bool close_sell_orders(string symbol, bool condition, int close_bars, ENUM_TIMEFRAMES close_bar_period, long _magic_number);
|
||||
bool daily_timed_exit(string symbol, datetime exit_time, int delay_days, long _magic_number);
|
||||
bool daily_timed_profit_exit(string symbol, ENUM_TIMEFRAMES close_bar_period, string exit_time, string cw_tzone, int delay_days,
|
||||
long _magic_number);
|
||||
bool daily_timed_profit_exit(string symbol, ENUM_TIMEFRAMES close_bar_period, string exit_time, string cw_tzone, int delay_days, long _magic_number);
|
||||
bool first_profitable_close_exit(string symbol, ENUM_TIMEFRAMES close_bar_period, long _magic_number);
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Closes BUY positions on condition + after a number of bars (if non 0) .
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Symbol to evaluate positions for.
|
||||
// - condition : If true, closes position immediately.
|
||||
// - close_bars : Minimum number of bars before auto close.
|
||||
// - close_bar_period : Timeframe to count bars on.
|
||||
// - _magic_number : Magic number to identify the trade group.
|
||||
//
|
||||
// Returns:
|
||||
// - True after evaluation and any attempted closes.
|
||||
// ---------------------------------------------------------------------
|
||||
bool ExitOrders::close_buy_orders(string symbol, bool condition, int close_bars, ENUM_TIMEFRAMES close_bar_period, long _magic_number) {
|
||||
for (int i = PositionsTotal() - 1; i >= 0; i--) {
|
||||
posTicket = PositionGetTicket(i);
|
||||
@@ -38,6 +50,19 @@ bool ExitOrders::close_buy_orders(string symbol, bool condition, int close_bars,
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Closes SELL positions on condition + after a number of bars (if non 0) .
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Symbol to evaluate positions for.
|
||||
// - condition : If true, closes position immediately.
|
||||
// - close_bars : Minimum number of bars before auto close.
|
||||
// - close_bar_period : Timeframe to count bars on.
|
||||
// - _magic_number : Magic number to identify the trade group.
|
||||
//
|
||||
// Returns:
|
||||
// - True after evaluation and any attempted closes.
|
||||
// ---------------------------------------------------------------------
|
||||
bool ExitOrders::close_sell_orders(string symbol, bool condition, int close_bars, ENUM_TIMEFRAMES close_bar_period, long _magic_number) {
|
||||
for (int i = PositionsTotal() - 1; i >= 0; i--) {
|
||||
posTicket = PositionGetTicket(i);
|
||||
@@ -55,6 +80,18 @@ bool ExitOrders::close_sell_orders(string symbol, bool condition, int close_bars
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Closes position after a fixed exit time and delay in days.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Symbol to evaluate.
|
||||
// - exit_time : Time of day when exit is permitted.
|
||||
// - delay_days : Number of full days before close allowed.
|
||||
// - _magic_number : Magic number to identify the trade group.
|
||||
//
|
||||
// Returns:
|
||||
// - True after evaluation and any attempted closes.
|
||||
// ---------------------------------------------------------------------
|
||||
bool ExitOrders::daily_timed_exit(string symbol, datetime exit_time, int delay_days, long _magic_number) {
|
||||
for (int i = PositionsTotal() - 1; i >= 0; i--) {
|
||||
posTicket = PositionGetTicket(i);
|
||||
@@ -73,6 +110,20 @@ bool ExitOrders::daily_timed_exit(string symbol, datetime exit_time, int delay_d
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Closes a position only if it's profitable after a given time.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Symbol to evaluate.
|
||||
// - close_bar_period : Bar timeframe for bar-close evaluation.
|
||||
// - exit_time : Time of day when profit exit is checked.
|
||||
// - cw_tzone : Clockwork time zone for exit conversion.
|
||||
// - delay_days : Minimum days to wait before closing.
|
||||
// - _magic_number : Magic number to identify the trade group.
|
||||
//
|
||||
// Returns:
|
||||
// - True after evaluation and any attempted closes.
|
||||
// ---------------------------------------------------------------------
|
||||
bool ExitOrders::daily_timed_profit_exit(string symbol, ENUM_TIMEFRAMES close_bar_period, string exit_time, string cw_tzone, int delay_days,
|
||||
long _magic_number) {
|
||||
for (int i = PositionsTotal() - 1; i >= 0; i--) {
|
||||
@@ -108,6 +159,17 @@ bool ExitOrders::daily_timed_profit_exit(string symbol, ENUM_TIMEFRAMES close_ba
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Closes position on first profitable bar after one bar completes.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Symbol to evaluate.
|
||||
// - close_bar_period : Timeframe for bar-close evaluation.
|
||||
// - _magic_number : Magic number to identify the trade group.
|
||||
//
|
||||
// Returns:
|
||||
// - True after evaluation and any attempted closes.
|
||||
// ---------------------------------------------------------------------
|
||||
bool ExitOrders::first_profitable_close_exit(string symbol, ENUM_TIMEFRAMES close_bar_period, long _magic_number) {
|
||||
position_open_time = PositionGetInteger(POSITION_TIME);
|
||||
first_allowed_close_time = position_open_time + PeriodSeconds(close_bar_period);
|
||||
|
||||
@@ -12,6 +12,18 @@ class OrderTracker {
|
||||
int count_pending_orders(string symbol, ENUM_ORDER_TYPE order_type, long magic);
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Counts the number of open BUY or SELL positions for a given symbol.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Trading symbol (e.g., "EURUSD").
|
||||
// - order_side : 1 = BUY, 2 = SELL.
|
||||
// - magic_number : Magic number identifying strategy group.
|
||||
//
|
||||
// Returns:
|
||||
// - Number of matching open positions.
|
||||
// ---------------------------------------------------------------------
|
||||
int OrderTracker::count_open_positions(string symbol, int order_side, long magic_number) {
|
||||
int count = 0;
|
||||
|
||||
@@ -32,6 +44,16 @@ int OrderTracker::count_open_positions(string symbol, int order_side, long magic
|
||||
return count;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Counts all open positions for a symbol regardless of direction.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Trading symbol.
|
||||
// - magic_number : Magic number identifying strategy group.
|
||||
//
|
||||
// Returns:
|
||||
// - Total number of matching positions.
|
||||
// ---------------------------------------------------------------------
|
||||
int OrderTracker::count_all_positions(string symbol, long magic_number) {
|
||||
int count = 0;
|
||||
|
||||
@@ -46,6 +68,17 @@ int OrderTracker::count_all_positions(string symbol, long magic_number) {
|
||||
return count;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Counts pending orders of a specific type for a symbol and magic number.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Trading symbol.
|
||||
// - order_type : Type of pending order (e.g., ORDER_TYPE_BUY_STOP).
|
||||
// - magic : Magic number identifying strategy group.
|
||||
//
|
||||
// Returns:
|
||||
// - Number of matching pending orders.
|
||||
// ---------------------------------------------------------------------
|
||||
int OrderTracker::count_pending_orders(string symbol, ENUM_ORDER_TYPE order_type, long magic) {
|
||||
int count = 0;
|
||||
|
||||
|
||||
+24
-2
@@ -1,9 +1,20 @@
|
||||
class StopLogic {
|
||||
public:
|
||||
public:
|
||||
double sl_specified_value_switch(string sl_mode, double inp_sl_var, double value);
|
||||
double tp_specified_value_switch(string tp_mode, double inp_tp_var, double value);
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Selects stop loss value based on SL mode.
|
||||
//
|
||||
// Parameters:
|
||||
// - sl_mode : Stop loss mode ("SL_SPECIFIED_VALUE", etc).
|
||||
// - inp_sl_var : User-input SL value (pips, percent, etc).
|
||||
// - value : Directly specified SL value.
|
||||
//
|
||||
// Returns:
|
||||
// - `value` if SL mode is "SL_SPECIFIED_VALUE", otherwise `inp_sl_var`.
|
||||
// ---------------------------------------------------------------------
|
||||
double StopLogic::sl_specified_value_switch(string sl_mode, double inp_sl_var, double value) {
|
||||
if (sl_mode == "SL_SPECIFIED_VALUE") {
|
||||
return value;
|
||||
@@ -12,8 +23,19 @@ double StopLogic::sl_specified_value_switch(string sl_mode, double inp_sl_var, d
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Selects take profit value based on TP mode.
|
||||
//
|
||||
// Parameters:
|
||||
// - tp_mode : Take profit mode ("TP_SPECIFIED_VALUE", etc).
|
||||
// - inp_tp_var : User-input TP value (pips, percent, etc).
|
||||
// - value : Directly specified TP value.
|
||||
//
|
||||
// Returns:
|
||||
// - `value` if TP mode is "TP_SPECIFIED_VALUE", otherwise `inp_tp_var`.
|
||||
// ---------------------------------------------------------------------
|
||||
double StopLogic::tp_specified_value_switch(string tp_mode, double inp_tp_var, double value) {
|
||||
if (tp_mode == "SL_SPECIFIED_VALUE") {
|
||||
if (tp_mode == "TP_SPECIFIED_VALUE") {
|
||||
return value;
|
||||
} else {
|
||||
return inp_tp_var;
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
#include <Trade/Trade.mqh>
|
||||
|
||||
class TrailingLogic {
|
||||
protected:
|
||||
CTrade trade;
|
||||
|
||||
public:
|
||||
void break_even_stop(string symbol, ulong magic_number, int be_trigger_points, int be_puffer);
|
||||
void nnfx_trailing_stop(string symbol, double sl_var, double tp_var, double atr_value, ulong magic_number);
|
||||
};
|
||||
|
||||
void TrailingLogic::break_even_stop(string symbol, ulong magic_number, int be_trigger_points, int be_puffer) {
|
||||
for (int i = PositionsTotal() - 1; i >= 0; i--) {
|
||||
if (PositionGetString(POSITION_SYMBOL) == symbol && PositionGetInteger(POSITION_MAGIC) == magic_number) {
|
||||
int symbol_digits = (int) SymbolInfoInteger(symbol, SYMBOL_DIGITS);
|
||||
double symbol_point = SymbolInfoDouble(symbol, SYMBOL_POINT);
|
||||
double ask = NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_ASK), symbol_digits);
|
||||
double bid = NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_BID), symbol_digits);
|
||||
|
||||
if (be_trigger_points != 0) {
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if (PositionSelectByTicket(ticket)) {
|
||||
double position_open_price = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
double position_volume = PositionGetDouble(POSITION_VOLUME);
|
||||
double position_sl = PositionGetDouble(POSITION_SL);
|
||||
double position_tp = PositionGetDouble(POSITION_TP);
|
||||
ENUM_POSITION_TYPE position_type = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
|
||||
|
||||
if (position_type == POSITION_TYPE_BUY && bid > position_open_price + be_trigger_points * symbol_point) {
|
||||
double sl = NormalizeDouble(position_open_price + be_puffer * symbol_point, symbol_digits);
|
||||
if (sl > position_sl) {
|
||||
trade.PositionModify(ticket, sl, position_tp);
|
||||
Print("-----------------------------------Stop moved to break even");
|
||||
}
|
||||
}
|
||||
|
||||
if (position_type == POSITION_TYPE_SELL && ask < position_open_price - be_trigger_points * symbol_point) {
|
||||
double sl = NormalizeDouble(position_open_price - be_puffer * symbol_point, symbol_digits);
|
||||
if (sl < position_sl) {
|
||||
trade.PositionModify(ticket, sl, position_tp);
|
||||
Print("-----------------------------------Stop moved to break even");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TrailingLogic::nnfx_trailing_stop(string symbol, double sl_var, double tp_var, double atr_value, ulong magic_number) {
|
||||
for (int i = PositionsTotal() - 1; i >= 0; i--) {
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if (PositionSelectByTicket(ticket)) {
|
||||
if (PositionGetString(POSITION_SYMBOL) == symbol && PositionGetInteger(POSITION_MAGIC) == magic_number) {
|
||||
int symbol_digits = (int) SymbolInfoInteger(symbol, SYMBOL_DIGITS);
|
||||
double symbol_point = SymbolInfoDouble(symbol, SYMBOL_POINT);
|
||||
double ask = NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_ASK), symbol_digits);
|
||||
double bid = NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_BID), symbol_digits);
|
||||
|
||||
double position_open_price = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
double position_sl = PositionGetDouble(POSITION_SL);
|
||||
double position_tp = PositionGetDouble(POSITION_TP);
|
||||
ENUM_POSITION_TYPE position_type = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
|
||||
|
||||
if (position_type == POSITION_TYPE_BUY && bid > position_open_price + (atr_value * tp_var)) {
|
||||
double sl = NormalizeDouble(bid - (atr_value * sl_var), symbol_digits);
|
||||
if (sl > (position_sl + (atr_value * 0.5))) {
|
||||
trade.PositionModify(ticket, sl, position_tp);
|
||||
}
|
||||
}
|
||||
|
||||
if (position_type == POSITION_TYPE_SELL && ask < position_open_price - (atr_value * tp_var)) {
|
||||
double sl = NormalizeDouble(ask + (atr_value * sl_var), symbol_digits);
|
||||
if (sl < (position_sl + (atr_value * 0.5))) {
|
||||
trade.PositionModify(ticket, sl, position_tp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user