792 lines
16 KiB
Plaintext
792 lines
16 KiB
Plaintext
///////////////////////////////////////////////////////
|
||
//
|
||
// SaherElm IT Center MQL5 Class Library
|
||
// --------------------------------------
|
||
// Name: XCVolume
|
||
// Description: provides all Requirements for Volume Managing ...
|
||
//
|
||
//
|
||
// Maintainer:
|
||
// ------------
|
||
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
||
//
|
||
//////////////////////////////////////////////////////
|
||
//
|
||
// Global Properties ...
|
||
#property library
|
||
#property copyright "Copyright 2023, SaherElm IT Center"
|
||
#property link "https://www.saherelm.ir"
|
||
#property version "1.00"
|
||
#property strict
|
||
|
||
//
|
||
// Template Variables of Inputs for Using ...
|
||
// input group "Volume";
|
||
// input ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect = X_VOLUME_STATIC; // Volume Applying Type
|
||
// input double eaStaticVoluem = X_MIN_VOLUME; // Static Volume
|
||
// input double eaDynamicVolumeStepBalance = 0.0; // Step of Balance for Increase Volume
|
||
// input double eaDynamicVolumeStepVolume = X_MIN_VOLUME; // Step of Volume Increasing
|
||
// input double eaConstantRiskBalance = 0.0; // Constant Risk Balance per Trade
|
||
// input double eaConstantPercent = 0.0; // Constant Percent of Balance Per Trade
|
||
// input double eaConstantBalance = 0.0; // Constant Balance for Calculations
|
||
// XCVolume *eaVolume;
|
||
// eaVolume = new XCVolume();
|
||
// bool result = eaVolume.Init(
|
||
// eaVolumeSelect,
|
||
// eaStaticVoluem,
|
||
// eaDynamicVolumeStepBalance,
|
||
// eaDynamicVolumeStepVolume,
|
||
// eaConstantRiskBalance,
|
||
// eaConstantPercent,
|
||
// eaConstantBalance //
|
||
// );
|
||
// if (!result) {
|
||
// return INIT_FAILED;
|
||
// }
|
||
|
||
//
|
||
// Imports ...
|
||
#include "../Classes/x-saherelm.x-account.class.mq5"
|
||
#include "../Libraries/x-saherelm.x-trade.lib.mq5"
|
||
|
||
//
|
||
// Definitions ...
|
||
#define X_MIN_VOLUME 0.01
|
||
|
||
//
|
||
enum ENUM_X_VOLUME_SELECT_TYPE
|
||
{
|
||
X_VOLUME_NONE, // None
|
||
X_VOLUME_STATIC, // Static Volume
|
||
X_VOLUME_CURRENT, // Current Balance
|
||
X_VOLUME_EQUITY, // Current Equity
|
||
X_VOLUME_CONSTANT // Constant Value
|
||
};
|
||
|
||
//
|
||
bool IsValid(ENUM_X_VOLUME_SELECT_TYPE value)
|
||
{
|
||
//
|
||
bool result = false;
|
||
|
||
//
|
||
result = value != X_VOLUME_NONE;
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
//
|
||
string ToString(ENUM_X_VOLUME_SELECT_TYPE value)
|
||
{
|
||
//
|
||
string result = NULL;
|
||
|
||
//
|
||
result = EnumToString(value);
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// Implementation ...
|
||
class XCVolume : public XCBase
|
||
{
|
||
//
|
||
// Public ...
|
||
public:
|
||
//
|
||
// Props ...
|
||
XCAccount *account;
|
||
|
||
//
|
||
// Constructor ...
|
||
XCVolume()
|
||
{
|
||
//
|
||
account = new XCAccount();
|
||
|
||
//
|
||
Default();
|
||
}
|
||
|
||
//
|
||
// Deconstructor ...
|
||
~XCVolume()
|
||
{
|
||
//
|
||
ZeroMemory(account);
|
||
}
|
||
|
||
//
|
||
bool Init(
|
||
ENUM_X_VOLUME_SELECT_TYPE _SelectType,
|
||
double _StaticVolume,
|
||
double _DynamicVolumeStepBalance,
|
||
double _DynamicVolumeStepVolume,
|
||
double _ConstantRiskBalance,
|
||
double _ConstantPercent,
|
||
double _ConstantBalance //
|
||
)
|
||
{
|
||
//
|
||
bool result = false;
|
||
|
||
//
|
||
mVolumeType = _SelectType;
|
||
mStaticVolume = _StaticVolume;
|
||
mConstantPercent = _ConstantPercent;
|
||
mConstantBalance = _ConstantBalance;
|
||
mConstantRiskBalance = _ConstantRiskBalance;
|
||
mDynamicVolumeStepVolume = _DynamicVolumeStepVolume;
|
||
mDynamicVolumeStepBalance = _DynamicVolumeStepBalance;
|
||
|
||
//
|
||
result =
|
||
//
|
||
CanUseStaticVolume() ||
|
||
CanUseDynamicVolume() ||
|
||
CanUseConstantRiskBalance() ||
|
||
CanUseConstantBalancePercent()
|
||
//
|
||
;
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// Prperties ...
|
||
|
||
/**
|
||
* Get Volume Calculating Method ...
|
||
*
|
||
* @return (ENUM_X_VOLUME_SELECT_TYPE)
|
||
*/
|
||
ENUM_X_VOLUME_SELECT_TYPE VolumeType()
|
||
{
|
||
return mVolumeType;
|
||
}
|
||
|
||
/**
|
||
* Set Volume Calculating Method ...
|
||
*
|
||
* @param value: ENUM_X_VOLUME_SELECT_TYPE member ...
|
||
*/
|
||
void VolumeType(ENUM_X_VOLUME_SELECT_TYPE value)
|
||
{
|
||
mVolumeType = value;
|
||
}
|
||
|
||
/**
|
||
* Get Static Volume ...
|
||
*
|
||
* @return ( double )
|
||
*/
|
||
double StaticVolume()
|
||
{
|
||
return mStaticVolume;
|
||
}
|
||
|
||
/**
|
||
* Set Static Volume ...
|
||
*
|
||
* @param value: double
|
||
*/
|
||
void StaticVolume(double value)
|
||
{
|
||
//
|
||
value = NormalizeDouble(value, 0.01, 1);
|
||
|
||
//
|
||
mStaticVolume = value;
|
||
}
|
||
|
||
/**
|
||
* Get Dynamic Volume Step Balance ...
|
||
* used to Calculate Final Lottage ...
|
||
*
|
||
* @return ( double )
|
||
*/
|
||
double DynamicVolumeStepBalance()
|
||
{
|
||
return mDynamicVolumeStepBalance;
|
||
}
|
||
|
||
/**
|
||
* Set Dynamic Volume Step Balance ...
|
||
* used to Calculate Final Lottage ...
|
||
*
|
||
* @param value: Argument 1
|
||
*/
|
||
void DynamicVolumeStepBalance(double value)
|
||
{
|
||
//
|
||
value = NormalizeDouble(value, 0);
|
||
|
||
//
|
||
mDynamicVolumeStepBalance = value;
|
||
}
|
||
|
||
/**
|
||
* Get Dynamic Volume Step Volume ...
|
||
* used to Calculate Final Lottage ...
|
||
* how much increase Final Volume based oBalance Step ...
|
||
*
|
||
* @return ( double )
|
||
*/
|
||
double DynamicVolumeStepVolume()
|
||
{
|
||
return mDynamicVolumeStepVolume;
|
||
}
|
||
|
||
/**
|
||
* Get Dynamic Volume Step Volume ...
|
||
* used to Calculate Final Lottage ...
|
||
* how much increase Final Volume based oBalance Step ...
|
||
*
|
||
* @param value: double
|
||
*/
|
||
void DynamicVolumeStepVolume(double value)
|
||
{
|
||
//
|
||
value = NormalizeDouble(value, 0.01, 0.1);
|
||
|
||
//
|
||
mDynamicVolumeStepVolume = value;
|
||
}
|
||
|
||
/**
|
||
* Get Constant Balance Use for Dyamic Volume Calculation ...
|
||
*
|
||
* @return ( double )
|
||
*/
|
||
double ConstantBalance()
|
||
{
|
||
return mConstantBalance;
|
||
}
|
||
|
||
/**
|
||
* Set Constant Balance Use for Dyamic Volume Calculation ...
|
||
*
|
||
* @param value: Argument 1
|
||
*/
|
||
void ConstantBalance(double value)
|
||
{
|
||
//
|
||
value = NormalizeDouble(value, 0);
|
||
|
||
//
|
||
mConstantBalance = value;
|
||
}
|
||
|
||
/**
|
||
* Get Constant Risk Value Based on Account Currency ...
|
||
*
|
||
* @return ( double )
|
||
*/
|
||
double ConstantRiskBalance()
|
||
{
|
||
return mConstantRiskBalance;
|
||
}
|
||
|
||
/**
|
||
* Get Constant Risk Value Based on Account Currency ...
|
||
*
|
||
* @param value: double
|
||
*/
|
||
void ConstantRiskBalance(double value)
|
||
{
|
||
//
|
||
value = NormalizeDouble(value, 0);
|
||
|
||
//
|
||
mConstantRiskBalance = value;
|
||
}
|
||
|
||
/**
|
||
* Get Constant Percent Based On Selected Balance ...
|
||
*
|
||
* @return ( double )
|
||
*/
|
||
double ConstantPercent()
|
||
{
|
||
return mConstantPercent;
|
||
}
|
||
|
||
/**
|
||
* Set Constant Percent Based On Selected Balance ...
|
||
*
|
||
* @param value: double ...
|
||
*/
|
||
void ConstantPercent(double value)
|
||
{
|
||
//
|
||
value = NormalizeDouble(value, 0, 100);
|
||
|
||
//
|
||
mConstantPercent = value;
|
||
}
|
||
|
||
//
|
||
// Tools ...
|
||
|
||
/**
|
||
* Retrieve Balance based on Provided Volume Type ...
|
||
*
|
||
* @return ( double )
|
||
*/
|
||
double GetBalance()
|
||
{
|
||
//
|
||
double result = 0;
|
||
|
||
//
|
||
if (!IsValid(mVolumeType))
|
||
{
|
||
return result;
|
||
}
|
||
|
||
//
|
||
if (mConstantBalance > 0 &&
|
||
mVolumeType == X_VOLUME_CONSTANT)
|
||
{
|
||
result = mConstantBalance;
|
||
}
|
||
else if (mVolumeType == X_VOLUME_CURRENT)
|
||
{
|
||
result = account.GetBalance();
|
||
}
|
||
else if (mVolumeType == X_VOLUME_EQUITY)
|
||
{
|
||
result = account.GetEquity();
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Retrieve Balance based on Provided Volume Type ...
|
||
*
|
||
* @return ( double )
|
||
*/
|
||
double GetBalance(ENUM_X_VOLUME_SELECT_TYPE type)
|
||
{
|
||
//
|
||
double result = 0;
|
||
|
||
//
|
||
if (!IsValid(type))
|
||
{
|
||
return result;
|
||
}
|
||
|
||
//
|
||
if (mConstantBalance > 0 &&
|
||
type == X_VOLUME_CONSTANT)
|
||
{
|
||
result = mConstantBalance;
|
||
}
|
||
else if (type == X_VOLUME_CURRENT)
|
||
{
|
||
result = account.GetBalance();
|
||
}
|
||
else if (type == X_VOLUME_EQUITY)
|
||
{
|
||
result = account.GetEquity();
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Calculate Volume Based On Given Configuration ...
|
||
*
|
||
* @param symbol: string, Trading Symbol ...
|
||
* @param entry: double, Entry Price ...
|
||
* @param sl: double, Stop Loss Price ...
|
||
*
|
||
* @return ( double )
|
||
*/
|
||
double CalculateVolume(
|
||
string symbol,
|
||
double entry,
|
||
double sl //
|
||
)
|
||
{
|
||
//
|
||
double result = X_MIN_VOLUME;
|
||
|
||
//
|
||
bool has = false;
|
||
|
||
//
|
||
// Validate Args ...
|
||
has =
|
||
sl > 0 &&
|
||
entry > 0 &&
|
||
IsValid(symbol);
|
||
if (!has)
|
||
{
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// Retrieve Balance Type ...
|
||
double balance = GetBalance();
|
||
double points = GetPoints(symbol);
|
||
double riskPrice = MathAbs(entry - sl);
|
||
double riskInPoints = riskPrice / points;
|
||
|
||
//
|
||
has = CanUseStaticVolume();
|
||
if (has)
|
||
{
|
||
result = mStaticVolume;
|
||
}
|
||
|
||
//
|
||
has = CanUseDynamicVolume();
|
||
if (has)
|
||
{
|
||
//
|
||
double multiplier = balance / mDynamicVolumeStepBalance;
|
||
if (multiplier < 0)
|
||
{
|
||
multiplier = 1;
|
||
}
|
||
|
||
//
|
||
result = multiplier * mDynamicVolumeStepVolume;
|
||
}
|
||
|
||
//
|
||
has = CanUseConstantRiskBalance();
|
||
if (has)
|
||
{
|
||
//
|
||
result = account.CalculateVolume(
|
||
symbol,
|
||
mConstantRiskBalance,
|
||
riskInPoints //
|
||
);
|
||
}
|
||
|
||
//
|
||
has = CanUseConstantBalancePercent();
|
||
if (has)
|
||
{
|
||
//
|
||
double riskAmountPerBalance = (mConstantPercent * balance) / 100;
|
||
|
||
//
|
||
result = account.CalculateVolume(
|
||
symbol,
|
||
riskAmountPerBalance,
|
||
riskInPoints //
|
||
);
|
||
}
|
||
|
||
//
|
||
if (result < X_MIN_VOLUME)
|
||
{
|
||
result = X_MIN_VOLUME;
|
||
}
|
||
|
||
//
|
||
// Normalize Volume ...
|
||
result = NormalizeVolume(result, symbol);
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Calculate Volume Based On Given Configuration ...
|
||
*
|
||
* @param signal: XSignal instance reference, provided required Data ...
|
||
*
|
||
* @return ( double )
|
||
*/
|
||
double CalculateVolume(XSignal &signal)
|
||
{
|
||
//
|
||
double result = X_MIN_VOLUME;
|
||
|
||
//
|
||
if (!signal.IsValid())
|
||
{
|
||
return result;
|
||
}
|
||
|
||
//
|
||
result = CalculateVolume(
|
||
signal.symbol,
|
||
signal.entry,
|
||
signal.sl //
|
||
);
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Calculate Specified Percent of Selected Balance for Volume ...
|
||
*
|
||
* @param percent: double, percent of Balance Risking ...
|
||
* @param symbol: string, Trading Symbol ...
|
||
* @param entry: double, Entry Price ...
|
||
* @param sl: double Stop Loss Price ...
|
||
*
|
||
* @return ( double )
|
||
*/
|
||
double CalculateVolume(
|
||
ENUM_X_VOLUME_SELECT_TYPE selectType,
|
||
double percent,
|
||
string symbol,
|
||
double entry,
|
||
double sl //
|
||
)
|
||
{
|
||
//
|
||
double result = X_MIN_VOLUME;
|
||
|
||
//
|
||
bool has = false;
|
||
|
||
//
|
||
// Validate Args ...
|
||
has =
|
||
sl > 0 &&
|
||
entry > 0 &&
|
||
percent > 0 &&
|
||
IsValid(symbol) &&
|
||
IsValid(selectType) &&
|
||
(selectType == X_VOLUME_EQUITY ||
|
||
selectType == X_VOLUME_CURRENT);
|
||
if (!has)
|
||
{
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// Retrieve Balance Type ...
|
||
double points = GetPoints(symbol);
|
||
double riskPrice = MathAbs(entry - sl);
|
||
double balance = GetBalance(selectType);
|
||
double riskInPoints = riskPrice / points;
|
||
|
||
//
|
||
double riskAmountPerBalance = (percent * balance) / 100;
|
||
|
||
//
|
||
result = account.CalculateVolume(
|
||
symbol,
|
||
riskAmountPerBalance,
|
||
riskInPoints //
|
||
);
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// Protected ...
|
||
protected:
|
||
//
|
||
// Tools ...
|
||
|
||
/**
|
||
* Set Default Props ...
|
||
*/
|
||
void Default()
|
||
{
|
||
//
|
||
VolumeType(X_VOLUME_STATIC);
|
||
StaticVolume(0.01);
|
||
|
||
//
|
||
ConstantBalance(0);
|
||
ConstantPercent(0);
|
||
ConstantRiskBalance(0);
|
||
|
||
//
|
||
DynamicVolumeStepBalance(0);
|
||
DynamicVolumeStepVolume(0.01);
|
||
}
|
||
|
||
/**
|
||
* Check Configuration is Valid For Static Volume ...
|
||
*
|
||
* @return ( bool )
|
||
*/
|
||
bool CanUseStaticVolume()
|
||
{
|
||
//
|
||
bool result = false;
|
||
|
||
//
|
||
result = IsValid(mVolumeType);
|
||
if (!result)
|
||
{
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// Static Volume ...
|
||
result =
|
||
//
|
||
mVolumeType == X_VOLUME_STATIC &&
|
||
mStaticVolume > 0 &&
|
||
//
|
||
mDynamicVolumeStepBalance == 0 &&
|
||
//
|
||
mConstantBalance == 0 &&
|
||
mConstantPercent == 0 &&
|
||
mConstantRiskBalance == 0
|
||
//
|
||
;
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Check Configuration is Valid For Dynamic Volume ...
|
||
*
|
||
* @return ( bool )
|
||
*/
|
||
bool CanUseDynamicVolume()
|
||
{
|
||
//
|
||
bool result = false;
|
||
|
||
//
|
||
result = IsValid(mVolumeType);
|
||
if (!result)
|
||
{
|
||
return result;
|
||
}
|
||
|
||
//
|
||
result =
|
||
//
|
||
(mVolumeType == X_VOLUME_CURRENT ||
|
||
mVolumeType == X_VOLUME_EQUITY ||
|
||
(mVolumeType == X_VOLUME_CONSTANT &&
|
||
mConstantBalance > 0)) &&
|
||
//
|
||
mDynamicVolumeStepBalance > 0 &&
|
||
mDynamicVolumeStepVolume > 0 &&
|
||
//
|
||
mStaticVolume == 0 &&
|
||
mConstantPercent == 0 &&
|
||
mConstantRiskBalance == 0
|
||
//
|
||
;
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Check Configuration is Valid For Constant Risk Balance ...
|
||
*
|
||
* @return ( bool )
|
||
*/
|
||
bool CanUseConstantRiskBalance()
|
||
{
|
||
//
|
||
bool result = false;
|
||
|
||
//
|
||
result = IsValid(mVolumeType);
|
||
if (!result)
|
||
{
|
||
return result;
|
||
}
|
||
|
||
//
|
||
result =
|
||
//
|
||
(mVolumeType == X_VOLUME_CURRENT ||
|
||
mVolumeType == X_VOLUME_EQUITY ||
|
||
(mVolumeType == X_VOLUME_CONSTANT &&
|
||
mConstantBalance > 0)) &&
|
||
//
|
||
mConstantRiskBalance > 0 &&
|
||
//
|
||
mStaticVolume == 0 &&
|
||
mConstantPercent == 0 &&
|
||
mDynamicVolumeStepBalance == 0
|
||
//
|
||
;
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Check Configuration is Valid For Constant Risk Percent ...
|
||
*
|
||
* @return ( bool )
|
||
*/
|
||
bool CanUseConstantBalancePercent()
|
||
{
|
||
//
|
||
bool result = false;
|
||
|
||
//
|
||
result = IsValid(mVolumeType);
|
||
if (!result)
|
||
{
|
||
return result;
|
||
}
|
||
|
||
//
|
||
result =
|
||
//
|
||
(mVolumeType == X_VOLUME_CURRENT ||
|
||
mVolumeType == X_VOLUME_EQUITY ||
|
||
(mVolumeType == X_VOLUME_CONSTANT &&
|
||
mConstantBalance > 0)) &&
|
||
//
|
||
mConstantPercent > 0 &&
|
||
//
|
||
mStaticVolume == 0 &&
|
||
mConstantRiskBalance == 0 &&
|
||
mDynamicVolumeStepBalance == 0
|
||
//
|
||
;
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// Private ...
|
||
private:
|
||
//
|
||
// Props ...
|
||
|
||
//
|
||
ENUM_X_VOLUME_SELECT_TYPE mVolumeType; // Balance Type ...
|
||
|
||
//
|
||
// Static Volume ...
|
||
double mStaticVolume; // Static Volume ...
|
||
|
||
//
|
||
double mDynamicVolumeStepBalance; // Step of Balance ...
|
||
double mDynamicVolumeStepVolume; // Step of Volume ...
|
||
|
||
//
|
||
double mConstantBalance; // Constant Balance ....
|
||
double mConstantRiskBalance; // Constant Risk Balance ...
|
||
double mConstantPercent; // Constant Percent of Balance ...
|
||
};
|
||
|
||
// |