MQLArticles/PosManagement/Breakeven.mqh

721 lines
61 KiB
MQL5
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//+------------------------------------------------------------------+
//| Breakeven.mqh |
//| Copyright 2025, Niquel y Leo. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Niquel y Leo."
#property link "https://www.mql5.com"
#property strict
#ifndef BREAKEVEN_MQH
#define BREAKEVEN_MQH
#include "..\\RM\\RiskManagement.mqh"
//+------------------------------------------------------------------+
//| Break Even Structs |
//+------------------------------------------------------------------+
struct position_be
{
ulong ticket; //Position Ticket
double breakeven_price; //Be price
double price_to_beat; //Price to exceed to reach break even
ENUM_POSITION_TYPE type;//Position type
};
enum ENUM_BREAKEVEN_TYPE
{
BREAKEVEN_TYPE_RR = 0, //By RR
BREAKEVEN_TYPE_FIXED_POINTS = 1, //By FixedPoints
BREAKEVEN_TYPE_ATR = 2 //By Atr
};
struct BreakEvenParams
{
long integer_value;
string string_value;
double double_value;
CAtrUltraOptimized* atr_pointer_value;
};
//---
class CBreakEvenBase;
class CBreakEven;
class CBreakEvenAtr;
class CBreakEvenRR;
class CBreakEvenSimple;
//---
#define CBREAKEVEN_RESERVE_REMOVE_BE_ARR 3
#define CBREAKEVEN_RESERVE_ARR 3
//+------------------------------------------------------------------+
//| Main class to apply break even |
//+------------------------------------------------------------------+
class CBreakEvenBase : public CAccountGestor
{
private:
int m_indices_to_remove_be[];
protected:
CTrade obj_trade; //CTrade object
MqlTick tick; //tick structure
string symbol; //current symbol
double point_value; //value of the set symbol point
position_be PostionsBe[]; //array of positions of type Positions
ulong magic; //magic number of positions to make break even
bool pause; //Boolean variable to activate the pause of the review, this is used to prevent the array from going out of range
int num_params; //Number of parameters the class needs
bool m_automatic;
public:
CBreakEvenBase(string symbol_, ulong magic_);
//---
inline bool Automatic() const { return m_automatic; }
void Automatic(bool auto) { m_automatic = auto; }
//---
inline string Simbolo() const { return symbol; }
inline ulong Magic() const { return magic; }
//---
inline int GetNumParams() const { return num_params; }
//--- General
virtual bool Add(ulong post_ticket, double open_price, double sl_price, ENUM_POSITION_TYPE position_type, datetime open_time) = 0;
void BreakEven();
void OnOpenClosePosition(const ROnOpenClosePosition &pos) override;
//--- Setter principal
virtual void Set(BreakEvenParams &params[]) = 0;
};
//+------------------------------------------------------------------+
//| Contructor |
//+------------------------------------------------------------------+
CBreakEvenBase::CBreakEvenBase(string symbol_, ulong magic_)
: pause(false), m_automatic(true)
{
if(magic_ != NOT_MAGIC_NUMBER)
obj_trade.SetExpertMagicNumber(magic_);
obj_trade.LogLevel(LOG_LEVEL_NO);
//---
this.symbol = symbol_;
this.num_params = 0;
this.magic = magic_;
this.point_value = SymbolInfoDouble(symbol_, SYMBOL_POINT);
//---
ArrayResize(PostionsBe, 0, CBREAKEVEN_RESERVE_ARR);
}
//+------------------------------------------------------------------+
//| OnTradeTransactionEvent |
//+------------------------------------------------------------------+
void CBreakEvenBase::OnOpenClosePosition(const ROnOpenClosePosition &pos)
{
if(m_automatic && pos.deal_entry_type == DEAL_ENTRY_IN)
{
const ulong position_magic = pos.position.magic;
if((this.magic == position_magic || this.magic == NOT_MAGIC_NUMBER))
{
if(Add(pos.position.ticket, pos.position.open_price, pos.position.firt_sl, pos.position.type, pos.position.open_time))
LogInfo(StringFormat("Ticket %I64u has been added to the array of positions", pos.position.ticket), FUNCION_ACTUAL);
}
return;
}
if(pos.deal_entry_type == DEAL_ENTRY_OUT)
{
this.pause = true;
if(RemoveIndexFromAnArrayOfPositions(PostionsBe, pos.position.ticket, CBREAKEVEN_RESERVE_ARR))
LogCaution(StringFormat("Ticket %I64u has been removed from the positions array, breakeven could not be applied", pos.position.ticket), FUNCION_ACTUAL);
this.pause = false;
}
}
//+------------------------------------------------------------------+
//| Function to make break even |
//+------------------------------------------------------------------+
void CBreakEvenBase::BreakEven(void)
{
if(this.PostionsBe.Size() < 1 || pause)
return;
SymbolInfoTick(this.symbol, tick);
//---
ArrayResize(m_indices_to_remove_be, 0, CBREAKEVEN_RESERVE_REMOVE_BE_ARR);
//---
for(int i = 0 ; i < ArraySize(this.PostionsBe) ; i++)
{
ulong ticket = this.PostionsBe[i].ticket;
if(tick.ask >= this.PostionsBe[i].price_to_beat && this.PostionsBe[i].type == POSITION_TYPE_BUY)
{
double position_tp = PositionGetDouble(POSITION_TP);
obj_trade.PositionModify(ticket, this.PostionsBe[i].breakeven_price, position_tp);
AddArrayNoVerification(m_indices_to_remove_be, i, CBREAKEVEN_RESERVE_REMOVE_BE_ARR);
}
else
if(tick.bid <= this.PostionsBe[i].price_to_beat && this.PostionsBe[i].type == POSITION_TYPE_SELL)
{
double position_tp = PositionGetDouble(POSITION_TP);
obj_trade.PositionModify(ticket, this.PostionsBe[i].breakeven_price, position_tp);
AddArrayNoVerification(m_indices_to_remove_be, i, CBREAKEVEN_RESERVE_REMOVE_BE_ARR);
}
}
RemoveMultipleIndexes(this.PostionsBe, m_indices_to_remove_be, CBREAKEVEN_RESERVE_REMOVE_BE_ARR);
}
//+------------------------------------------------------------------+
//| class CBreakEvenSimple |
//+------------------------------------------------------------------+
class CBreakEvenSimple : public CBreakEvenBase
{
private:
int extra_points_be, points_be;
public:
CBreakEvenSimple(string symbol_, ulong magic_)
: CBreakEvenBase(symbol_, magic_) { this.extra_points_be = 0; this.points_be = 0; this.num_params = 2;}
bool Add(ulong post_ticket, double open_price, double sl_price, ENUM_POSITION_TYPE position_type, datetime open_time) override;
void Set(BreakEvenParams &params[]) override;
void SetSetSimple(int points_be_, int extra_points_be_);
};
//+----------------------------------------------------------------------------------------------+
//| Create a new structure and add it to the main array using the 'AddToArrayBe' function |
//+----------------------------------------------------------------------------------------------+
bool CBreakEvenSimple::Add(ulong post_ticket, double open_price, double sl_price, ENUM_POSITION_TYPE position_type, datetime open_time)
{
position_be new_pos;
new_pos.breakeven_price = position_type == POSITION_TYPE_BUY ? open_price + (point_value * extra_points_be) : open_price - (point_value * extra_points_be);
new_pos.type = position_type;
new_pos.price_to_beat = position_type == POSITION_TYPE_BUY ? open_price + (point_value * points_be) : open_price - (point_value * points_be) ;
new_pos.ticket = post_ticket;
AddArrayNoVerification(this.PostionsBe, new_pos, CBREAKEVEN_RESERVE_ARR);
return true;
}
//+------------------------------------------------------------------+
//| Set attributes of CBreakEvenSimple class with MqlParam array |
//+------------------------------------------------------------------+
void CBreakEvenSimple::Set(BreakEvenParams &params[])
{
if(params.Size() < 2)
{
LogCriticalError(StringFormat("MqlParams array size is less than 2", params.Size()), FUNCION_ACTUAL);
ExpertRemove();
return;
}
SetSetSimple(int(params[0].integer_value), int(params[1].integer_value));
}
//+------------------------------------------------------------------+
//| Function to set member variables without using MalParams |
//+------------------------------------------------------------------+
void CBreakEvenSimple::SetSetSimple(int points_be_, int extra_points_be_)
{
if(points_be_ <= 0)
{
LogError(StringFormat("The points to set the breakeven %I32d are invalid.", points_be_), FUNCION_ACTUAL);
ExpertRemove();
return;
}
if(extra_points_be_ < 0)
{
LogFatalError(StringFormat("The extra points %I32d for the breakeven price are invalid.", extra_points_be_), FUNCION_ACTUAL);
ExpertRemove();
return;
}
if(extra_points_be_ >= points_be_)
{
LogWarning("The break even points (breakeven_price) is greater than the breakeven points (price_to_beat)\nTherefore the value of the extra breakeven points will be modified 0.", FUNCION_ACTUAL);
this.points_be = points_be_; //0
this.extra_points_be = 0; //1
return;
}
this.points_be = points_be_; //0
this.extra_points_be = extra_points_be_; //1
}
//+------------------------------------------------------------------+
//| Class to apply break even based on atr |
//+------------------------------------------------------------------+
#define POINTER_INSTEAD_OF_PERIOD 0
//--- class CBreakEvenAtr
class CBreakEvenAtr : public CBreakEvenBase
{
private:
CAtrUltraOptimized* atr_ultra;
double atr_multiplier_be;
double atr_multiplier_extra_be;
public:
CBreakEvenAtr(string symbol_, ulong magic_)
: CBreakEvenBase(symbol_, magic_), atr_multiplier_be(1.0), atr_multiplier_extra_be(1.0)
{ this.num_params = 5; }
bool Add(ulong post_ticket, double open_price, double sl_price, ENUM_POSITION_TYPE position_type, datetime open_time) override;
void Set(BreakEvenParams &params[]) override;
void SetSimple(CAtrUltraOptimized * atr_pointer, double atr_multiplier_extra_be_, double atr_multiplier_be_);
void SetSimple(int atr_period, int atr_idx_, double atr_multiplier_extra_be_, double atr_multiplier_be_, ENUM_TIMEFRAMES timeframe);
};
//+------------------------------------------------------------------+
//| Function to set CBreakEvenAtr variables with MqlParams array |
//+------------------------------------------------------------------+
void CBreakEvenAtr::Set(BreakEvenParams &params[])
{
if(params.Size() < 5)
{
LogError(StringFormat("The size of the array MqlParams %I32u to set the atr is less than 5", params.Size()), FUNCION_ACTUAL);
ExpertRemove();
return;
}
if(params[4].integer_value == POINTER_INSTEAD_OF_PERIOD) //4
{
/*
this.atr_pointer = (int)params[0].atr_pointer_value; //0
this.atr_multiplier_be = params[1].double_value; //1
this.atr_multiplier_extra_be = params[2].double_value; //2
*/
SetSimple(params[0].atr_pointer_value, params[2].double_value, params[1].double_value);
}
else
{
/*
this.atr_idx = (int)params[0].integer_value; //0
this.atr_multiplier_be = params[1].double_value; //1
this.atr_multiplier_extra_be = params[2].double_value; //2
ENUM_TIMEFRAMES timeframe = (ENUM_TIMEFRAMES)params[3].integer_value; //3
int period = (int)params[4].integer_value; //4
*/
SetSimple((int)params[4].integer_value, (int)params[0].integer_value, params[2].double_value, params[1].double_value, (ENUM_TIMEFRAMES)params[3].integer_value);
}
}
//+------------------------------------------------------------------------------------+
//| Function to set the values of the CBreakEvenAtr class without using MqlParams |
//| Using the handle instead of period and timeframe |
//+------------------------------------------------------------------------------------+
void CBreakEvenAtr::SetSimple(CAtrUltraOptimized* atr_pointer, double atr_multiplier_extra_be_, double atr_multiplier_be_)
{
if(atr_multiplier_extra_be_ >= atr_multiplier_be_)
{
LogError("The multiplier of the atr to calculate the price be is greater than or equal to the multiplier to set the be", FUNCION_ACTUAL);
Remover();
return;
}
if(CheckPointer(atr_pointer) == POINTER_INVALID)
{
LogFatalError("El puntero a CAtrUltraOptimized* es invaldio", FUNCION_ACTUAL);
Remover();
return;
}
this.atr_ultra = atr_pointer;
this.atr_multiplier_be = atr_multiplier_be_;
this.atr_multiplier_extra_be = atr_multiplier_extra_be_;
}
//+------------------------------------------------------------------------------------+
//| Function to set the values of the CBreakEvenAtr class without using MqlParams |
//| Configuring the handle with the period and timeframe. |
//+------------------------------------------------------------------------------------+
void CBreakEvenAtr::SetSimple(int atr_period, int atr_idx_, double atr_multiplier_extra_be_, double atr_multiplier_be_, ENUM_TIMEFRAMES timeframe)
{
CAtrUltraOptimized* atr_op = new CAtrUltraOptimized();
atr_op.SetVariables(timeframe, this.symbol, atr_idx_, atr_period);
atr_op.SetInternalPointer();
SetSimple(atr_op, atr_multiplier_extra_be_, atr_multiplier_be_);
}
//+------------------------------------------------------------------+
//| Function to add an element to the positions array |
//+------------------------------------------------------------------+
bool CBreakEvenAtr::Add(ulong post_ticket, double open_price, double sl_price, ENUM_POSITION_TYPE position_type, datetime open_time)
{
double val = atr_ultra.base.GetAtrValue(open_time);
position_be new_pos;
new_pos.breakeven_price = position_type == POSITION_TYPE_BUY ? open_price + (val * atr_multiplier_extra_be) : open_price - (val * atr_multiplier_extra_be);
new_pos.type = position_type;
new_pos.price_to_beat = position_type == POSITION_TYPE_BUY ? open_price + (val * atr_multiplier_be) : open_price - (val * atr_multiplier_be);
new_pos.ticket = post_ticket;
AddArrayNoVerification(this.PostionsBe, new_pos, CBREAKEVEN_RESERVE_ARR);
return true;
}
//+------------------------------------------------------------------+
//| CBreakEvenRR Class |
//+------------------------------------------------------------------+
enum ENUM_TYPE_EXTRA_BE_BY_RRR
{
EXTRA_BE_RRR_BY_ATR, //By Atr
EXTRA_BE_RRR_BY_FIXED_POINTS //By Fixed Points
};
//--- class CBreakEvenRR
class CBreakEvenRR : public CBreakEvenBase
{
private:
CAtrUltraOptimized* atr_ultra;
double coefficient_rr; //Coefficient of rr
ENUM_TYPE_EXTRA_BE_BY_RRR type;
double extra_value_be; //Extra value that will be added to the opening price of the position to obtain the breakeven price
//Note: if the type is atr this will contain the atr multiplier, if not it will contain the value already multiplied by the point value
public:
CBreakEvenRR(string symbol_, ulong magic_);
bool Add(ulong post_ticket, double open_price, double sl_price, ENUM_POSITION_TYPE position_type, datetime open_time) override;
void Set(BreakEvenParams &params[]) override;
void SetSimple(double rr_a_put_the_break_even, ENUM_TYPE_EXTRA_BE_BY_RRR type_extra, double atr_multiplier_or_extra_points, CAtrUltraOptimized * atr_ptr);
void SetSimple(double rr_a_put_the_break_even, ENUM_TYPE_EXTRA_BE_BY_RRR type_extra, double atr_multiplier_or_extra_points, int idx_atr_, ENUM_TIMEFRAMES tf_atr, int atr_period_);
};
//+------------------------------------------------------------------+
//| Contructor |
//+------------------------------------------------------------------+
void CBreakEvenRR::CBreakEvenRR(string symbol_, ulong magic_)
: CBreakEvenBase(symbol_, magic_),
coefficient_rr(1.0),
extra_value_be(100.0),
type(EXTRA_BE_RRR_BY_FIXED_POINTS)
{
this.num_params = 6;
}
//+------------------------------------------------------------------+
//| Function to set break even values by rr with MqlParams |
//+------------------------------------------------------------------+
void CBreakEvenRR::Set(BreakEvenParams &params[])
{
if((int)params.Size() < num_params)
{
LogError(StringFormat("The size of the MqlParams array %I32u to set the be by rr is less than 2", params.Size()), FUNCION_ACTUAL);
ExpertRemove();
return;
}
if(params[5].integer_value == POINTER_INSTEAD_OF_PERIOD)
{
//-> (0)double rr_a_put_the_break_even,(1) ENUM_TYPE_EXTRA_BE_BY_RRR type_extra, (2)double atr_multiplier_or_extra_points, (3)int idx_atr_, (4)int atr_handle_
SetSimple(params[0].double_value, (ENUM_TYPE_EXTRA_BE_BY_RRR)params[1].integer_value, params[2].double_value, params[4].atr_pointer_value);
}
else
{
//-> (0)double rr_a_put_the_break_even,(1) ENUM_TYPE_EXTRA_BE_BY_RRR type_extra, (2)double atr_multiplier_or_extra_points, (3)int idx_atr_, (4)ENUM_TIMEFRAMES tf_atr, (5)int atr_period_
SetSimple(params[0].double_value, (ENUM_TYPE_EXTRA_BE_BY_RRR)params[1].integer_value, params[2].double_value, (int)params[3].integer_value, (ENUM_TIMEFRAMES)params[4].integer_value, (int)params[5].integer_value);
}
}
//+------------------------------------------------------------------+
//| Function to set break even values by rr without MqlParams |
//+------------------------------------------------------------------+
void CBreakEvenRR::SetSimple(double rr_a_put_the_break_even, ENUM_TYPE_EXTRA_BE_BY_RRR type_extra, double atr_multiplier_or_extra_points, CAtrUltraOptimized* atr_ptr)
{
ResetLastError();
if(coefficient_rr <= 0.00)
{
LogCriticalError(StringFormat("The %+f coefficient of 'reward' is invalid", coefficient_rr), FUNCION_ACTUAL);
ExpertRemove();
return;
}
if(atr_multiplier_or_extra_points <= 0.00)
{
LogCriticalError(StringFormat("The atr multiplier or extra points %f is less than or equal to 0", atr_multiplier_or_extra_points), FUNCION_ACTUAL);
ExpertRemove();
return;
}
if(type_extra != EXTRA_BE_RRR_BY_ATR && type_extra != EXTRA_BE_RRR_BY_FIXED_POINTS)
{
LogCriticalError(StringFormat("The type of extra value %s is invalid", EnumToString(type_extra)), FUNCION_ACTUAL);
ExpertRemove();
return;
}
this.type = type_extra;
this.coefficient_rr = rr_a_put_the_break_even;
if(type_extra == EXTRA_BE_RRR_BY_ATR)
{
if(CheckPointer(atr_ptr) == POINTER_INVALID)
{
LogFatalError("El puntero 'atr_ptr' es invalido", FUNCION_ACTUAL);
ExpertRemove();
return;
}
this.atr_ultra = atr_ptr;
this.extra_value_be = atr_multiplier_or_extra_points;
}
else
this.extra_value_be = atr_multiplier_or_extra_points * this.point_value;
}
//+------------------------------------------------------------------+
//| Function to set break even values by rr without MqlParams |
//+------------------------------------------------------------------+
void CBreakEvenRR::SetSimple(double rr_a_put_the_break_even, ENUM_TYPE_EXTRA_BE_BY_RRR type_extra, double atr_multiplier_or_extra_points, int idx_atr_, ENUM_TIMEFRAMES tf_atr, int atr_period_)
{
if(type_extra != EXTRA_BE_RRR_BY_ATR && type_extra != EXTRA_BE_RRR_BY_FIXED_POINTS)
{
LogCriticalError(StringFormat("The type of extra value %s is invalid", EnumToString(type_extra)), FUNCION_ACTUAL);
ExpertRemove();
return;
}
if(atr_period_ < 0)
{
LogError(StringFormat("The atr period %d is invalid", atr_period_), FUNCION_ACTUAL);
ExpertRemove();
return;
}
if(type_extra == EXTRA_BE_RRR_BY_ATR)
{
CAtrUltraOptimized* atr_ptr = new CAtrUltraOptimized();
atr_ptr.SetVariables(tf_atr, this.symbol, idx_atr_, atr_period_);
atr_ptr.SetInternalPointer();
SetSimple(rr_a_put_the_break_even, type_extra, atr_multiplier_or_extra_points, atr_ptr);
return;
}
SetSimple(rr_a_put_the_break_even, type_extra, atr_multiplier_or_extra_points, NULL);
}
//+------------------------------------------------------------------+
//| Function to add an element to the positions array |
//+------------------------------------------------------------------+
bool CBreakEvenRR::Add(ulong post_ticket, double open_price, double sl_price, ENUM_POSITION_TYPE position_type, datetime open_time)
{
if(sl_price <= 0.00)
{
LogError(StringFormat("Position %I64u with stop loss %+f has sl less than 0", post_ticket, sl_price), FUNCION_ACTUAL);
return false;
}
double val = this.extra_value_be;
if(type == EXTRA_BE_RRR_BY_ATR)
{
val *= atr_ultra.base.GetAtrValue(open_time);
}
double diff = fabs(open_price - sl_price);
if((diff * coefficient_rr) <= val)
{
LogError(StringFormat("The distance from the opening price %f where the stoploss is located is greater than or equal to the price to trigger the breakeven", this.extra_value_be), FUNCION_ACTUAL);
return false;
}
position_be new_pos;
new_pos.breakeven_price = position_type == POSITION_TYPE_BUY ? open_price + val : open_price - val;
new_pos.type = position_type;
new_pos.price_to_beat = position_type == POSITION_TYPE_BUY ? open_price + (coefficient_rr * diff) : open_price - (coefficient_rr * diff);
new_pos.ticket = post_ticket;
LogInfo(StringFormat("El precio del nuevo stop loss sera %f, valor actual del atr[%d] = %f", new_pos.breakeven_price, atr_ultra.Index(), val), FUNCION_ACTUAL);
AddArrayNoVerification(this.PostionsBe, new_pos, CBREAKEVEN_RESERVE_ARR);
return true;
}
//+------------------------------------------------------------------+
//| CBreakEven class |
//+------------------------------------------------------------------+
struct BreakEvenParamsInfo
{
BreakEvenParams params[];
};
//---
class CBreakEven
{
private:
ulong magic;
string symbol;
BreakEvenParamsInfo parameters[];
CBreakEvenBase * CreateBreakEven(ENUM_BREAKEVEN_TYPE type);
public:
CBreakEven(ulong magic_, string symbol_);
~CBreakEven();
CBreakEvenBase* obj;
//--- Setters
void SetInternalPointer(ENUM_BREAKEVEN_TYPE type);
void SetBeByFixedPoints(int points_be_, int extra_points_be_);
void SetBeByAtr(int atr_period, int atr_idx_, double atr_multiplier_extra_be_, double atr_multiplier_be_, ENUM_TIMEFRAMES timeframe);
void SetBeByAtr(double atr_multiplier_be, double atr_multiplier_extra_be, CAtrUltraOptimized* atr_ptr);
void SetBeByRR(double rr_a_put_the_break_even, ENUM_TYPE_EXTRA_BE_BY_RRR type_extra, double atr_multiplier_or_extra_points, CAtrUltraOptimized* atr_ptr);
void SetBeByRR(double rr_a_put_the_break_even, ENUM_TYPE_EXTRA_BE_BY_RRR type_extra, double atr_multiplier_or_extra_points, int idx_atr_, ENUM_TIMEFRAMES tf_atr, int atr_period_);
};
//+------------------------------------------------------------------+
//| Contructor |
//+------------------------------------------------------------------+
CBreakEven::CBreakEven(ulong magic_, string symbol_)
{
this.magic = magic_;
this.symbol = symbol_;
obj = NULL;
ArrayResize(parameters, 3);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CBreakEven::~CBreakEven()
{
//Obj is not deleted since it works with CAccountStatus, without it it cannot do anything
}
//+------------------------------------------------------------------+
//| Set rr without handle |
//+------------------------------------------------------------------+
void CBreakEven::SetBeByRR(double rr_a_put_the_break_even, ENUM_TYPE_EXTRA_BE_BY_RRR type_extra, double atr_multiplier_or_extra_points, int idx_atr_, ENUM_TIMEFRAMES tf_atr, int atr_period_)
{
ArrayResize(parameters[int(BREAKEVEN_TYPE_RR)].params, 6);
parameters[BREAKEVEN_TYPE_RR].params[0].double_value = rr_a_put_the_break_even;
parameters[BREAKEVEN_TYPE_RR].params[1].integer_value = (int)type_extra;
parameters[BREAKEVEN_TYPE_RR].params[2].double_value = atr_multiplier_or_extra_points;
parameters[BREAKEVEN_TYPE_RR].params[3].integer_value = idx_atr_;
parameters[BREAKEVEN_TYPE_RR].params[4].integer_value = (int)tf_atr;
parameters[BREAKEVEN_TYPE_RR].params[5].integer_value = atr_period_;
}
//+------------------------------------------------------------------+
//| Set rr with handle |
//+------------------------------------------------------------------+
void CBreakEven::SetBeByRR(double rr_a_put_the_break_even, ENUM_TYPE_EXTRA_BE_BY_RRR type_extra, double atr_multiplier_or_extra_points, CAtrUltraOptimized* atr_ptr)
{
ArrayResize(parameters[int(BREAKEVEN_TYPE_RR)].params, 6);
parameters[BREAKEVEN_TYPE_RR].params[0].double_value = rr_a_put_the_break_even;
parameters[BREAKEVEN_TYPE_RR].params[1].integer_value = (int)type_extra;
parameters[BREAKEVEN_TYPE_RR].params[2].double_value = atr_multiplier_or_extra_points;
parameters[BREAKEVEN_TYPE_RR].params[3].integer_value = 0;
parameters[BREAKEVEN_TYPE_RR].params[4].atr_pointer_value = atr_ptr;
parameters[BREAKEVEN_TYPE_RR].params[5].integer_value = POINTER_INSTEAD_OF_PERIOD;
}
//+------------------------------------------------------------------+
//| Set atr (without handle) |
//+------------------------------------------------------------------+
void CBreakEven::SetBeByAtr(int atr_period, int atr_idx_, double atr_multiplier_extra_be_, double atr_multiplier_be_, ENUM_TIMEFRAMES timeframe)
{
ArrayResize(parameters[int(BREAKEVEN_TYPE_ATR)].params, 5);
parameters[BREAKEVEN_TYPE_ATR].params[0].integer_value = atr_idx_;
parameters[BREAKEVEN_TYPE_ATR].params[1].double_value = atr_multiplier_be_;
parameters[BREAKEVEN_TYPE_ATR].params[2].double_value = atr_multiplier_extra_be_;
parameters[BREAKEVEN_TYPE_ATR].params[3].integer_value = int(timeframe);
parameters[BREAKEVEN_TYPE_ATR].params[4].integer_value = atr_period;
}
//+------------------------------------------------------------------+
//| Set atr (with handle) |
//+------------------------------------------------------------------+
void CBreakEven::SetBeByAtr(double atr_multiplier_be, double atr_multiplier_extra_be, CAtrUltraOptimized* atr_ptr)
{
ArrayResize(parameters[int(BREAKEVEN_TYPE_ATR)].params, 5);
parameters[BREAKEVEN_TYPE_ATR].params[0].atr_pointer_value = atr_ptr;
parameters[BREAKEVEN_TYPE_ATR].params[1].double_value = atr_multiplier_be;
parameters[BREAKEVEN_TYPE_ATR].params[2].double_value = atr_multiplier_extra_be;
parameters[BREAKEVEN_TYPE_ATR].params[3].integer_value = 0;
parameters[BREAKEVEN_TYPE_ATR].params[4].integer_value = POINTER_INSTEAD_OF_PERIOD;
}
//+------------------------------------------------------------------+
//| Set Fixed Point be |
//+------------------------------------------------------------------+
void CBreakEven::SetBeByFixedPoints(int points_be_, int extra_points_be_)
{
ArrayResize(parameters[int(BREAKEVEN_TYPE_FIXED_POINTS)].params, 2);
parameters[BREAKEVEN_TYPE_FIXED_POINTS].params[0].integer_value = points_be_;
parameters[BREAKEVEN_TYPE_FIXED_POINTS].params[1].integer_value = extra_points_be_;
}
//+------------------------------------------------------------------+
//| Dynamically create the correct BreakEven |
//+------------------------------------------------------------------+
CBreakEvenBase * CBreakEven::CreateBreakEven(ENUM_BREAKEVEN_TYPE type)
{
switch(type)
{
case BREAKEVEN_TYPE_ATR:
return new CBreakEvenAtr(this.symbol, this.magic);
case BREAKEVEN_TYPE_RR:
return new CBreakEvenRR(this.symbol, this.magic);
case BREAKEVEN_TYPE_FIXED_POINTS:
return new CBreakEvenSimple(this.symbol, this.magic);
default:
return NULL;
}
}
//+------------------------------------------------------------------+
//| Set Pointer |
//+------------------------------------------------------------------+
void CBreakEven::SetInternalPointer(ENUM_BREAKEVEN_TYPE type)
{
if(CheckPointer(this.obj) == POINTER_DYNAMIC)
{
delete this.obj;
this.obj = NULL;
account_status.Remove(obj);
}
this.obj = CreateBreakEven(type);
if(this.obj == NULL)
{
printf("%s: Critical error | The type %d is invalid.", __FUNCTION__, type);
ExpertRemove();
return;
}
if((int)parameters[type].params.Size() < obj.GetNumParams())
{
printf("%s: Error | The parameter array for %s is too small (%I32u elements)",
__FUNCTION__, EnumToString(type), parameters[type].params.Size());
delete obj;
obj = NULL;
account_status.Remove(obj);
ExpertRemove();
return;
}
obj.Set(parameters[type].params);
//--- We link the object so that it has access to the account positions
account_status.AddItemFast(obj);
}
//+------------------------------------------------------------------+
#endif
//+------------------------------------------------------------------+