2651 lines
50 KiB
Plaintext
2651 lines
50 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Class Library
|
|
// --------------------------------------
|
|
// Name: XChartObjects
|
|
// Description: provides all require Chart Objects ...
|
|
//
|
|
//
|
|
// 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
|
|
|
|
//
|
|
#include "../Libraries/x-saherelm.x-pivot.analysis.lib.mq5"
|
|
#include "../Libraries/x-saherelm.x-poi.lib.mq5"
|
|
#include "../Libraries/x-saherelm.x-trade.lib.mq5"
|
|
|
|
//
|
|
#include <ChartObjects/ChartObject.mqh>
|
|
#include <ChartObjects/ChartObjectsArrows.mqh>
|
|
#include <ChartObjects/ChartObjectsFibo.mqh>
|
|
#include <ChartObjects/ChartObjectsLines.mqh>
|
|
#include <ChartObjects/ChartObjectsShapes.mqh>
|
|
#include <ChartObjects/ChartObjectsTxtControls.mqh>
|
|
|
|
//
|
|
// Definitions ...
|
|
|
|
enum ENUM_XCHARTOBJECTS
|
|
{
|
|
//
|
|
// Global ...
|
|
X_EMPTY_OBJ = 7860, // Empty
|
|
X_BOX_OBJ = 7861, // XBox
|
|
X_BAR_ARROW_OBJ = 7862, // XBarArrow
|
|
X_SIGNAL_OBJ = 8860, // XSignal
|
|
X_OHCL_OBJ = 8863, // XBar
|
|
X_RR_OBJ = 8864, // XRR
|
|
X_POSITION_OBJ = 8865, // XPosition
|
|
//
|
|
// 9860 Custom Object ...
|
|
};
|
|
|
|
enum ENUM_X_CHART_IDS
|
|
{
|
|
X_AT, // AT
|
|
X_TO, // TO
|
|
X_FROM, // FROM
|
|
X_UPPER, // UPPER
|
|
X_LOWER, // LOWER
|
|
X_ENTRY, // ENTRY
|
|
X_TARGET, // TARGET
|
|
X_SL, // SL
|
|
X_TP, // TP
|
|
X_BAR_H_SHW, // HSHW
|
|
X_BAR_BDY, // BODY
|
|
X_BAR_L_SHW, // LSHW
|
|
};
|
|
|
|
string ToString(ENUM_X_CHART_IDS value)
|
|
{
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
result = EnumToString(value);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
string ToXString(ENUM_XCHARTOBJECTS value)
|
|
{
|
|
//
|
|
return EnumToString(value);
|
|
}
|
|
|
|
struct XPOIStyle
|
|
{
|
|
//
|
|
// Properties ...
|
|
int width; // Width ...
|
|
color clr; // Color ...
|
|
bool fill; // Fill, Use in Rectangles ...
|
|
ENUM_LINE_STYLE style; // Line Style ...
|
|
|
|
//
|
|
// Constructor ...
|
|
XPOIStyle()
|
|
{
|
|
Default();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
// Cleanup Model ...
|
|
void Clean()
|
|
{
|
|
//
|
|
width = 1;
|
|
fill = false;
|
|
clr = CLR_NONE;
|
|
style = STYLE_SOLID;
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
//
|
|
// Default Props ...
|
|
void Default()
|
|
{
|
|
//
|
|
width = 1;
|
|
fill = false;
|
|
clr = CLR_NONE;
|
|
style = STYLE_SOLID;
|
|
}
|
|
};
|
|
|
|
//
|
|
// Extensions ...
|
|
|
|
/**
|
|
* Converts a XBoxZone struct to XSignal instance ...
|
|
*
|
|
* @param box: XBoxZone instance reference, provide source info ...
|
|
* @param signal: XSignal instance reference, holds prepared converted signal ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToXSignal(
|
|
XBoxZone &box,
|
|
XSignal &signal,
|
|
double &rewardRatios[],
|
|
double additionalSL = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
signal.Clean();
|
|
|
|
//
|
|
result = box.IsValid() &&
|
|
HasChild(rewardRatios);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL entryBar;
|
|
int entryIDX = box.ToIndex();
|
|
if (entryIDX > 0)
|
|
{
|
|
entryIDX--;
|
|
}
|
|
result = entryBar.Init(
|
|
box.symbol,
|
|
box.period,
|
|
entryIDX //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
entryBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = box.IsBullish();
|
|
bool isBearish = box.IsBearish();
|
|
|
|
//
|
|
ENUM_POSITION_TYPE iType =
|
|
isBullish
|
|
? POSITION_TYPE_BUY
|
|
: POSITION_TYPE_SELL;
|
|
ENUM_X_POSITION_TYPES iXType =
|
|
isBullish
|
|
? X_POSITION_TYPE_LONG
|
|
: X_POSITION_TYPE_SHORT;
|
|
|
|
//
|
|
double points = GetPoints(box.symbol);
|
|
|
|
//
|
|
double entry =
|
|
isBullish
|
|
? box.upper
|
|
: box.lower;
|
|
entry = entryBar.open;
|
|
|
|
//
|
|
double sl =
|
|
isBullish
|
|
? box.lower
|
|
: box.upper;
|
|
if (additionalSL > 0)
|
|
{
|
|
//
|
|
sl =
|
|
isBullish
|
|
? sl - additionalSL
|
|
: sl + additionalSL;
|
|
}
|
|
|
|
//
|
|
double risk = MathAbs(entry - sl);
|
|
|
|
//
|
|
double tp = 0;
|
|
|
|
//
|
|
// Calculate Target ...
|
|
XTarget targets[];
|
|
|
|
//
|
|
double tmp[];
|
|
int idx = -1;
|
|
XTarget iTarget;
|
|
bool has = false;
|
|
double iRatio = 0;
|
|
double iReward = 0;
|
|
double iRewardPrice = 0;
|
|
Copy(
|
|
rewardRatios,
|
|
tmp //
|
|
);
|
|
while (HasChild(tmp))
|
|
{
|
|
//
|
|
idx = -1;
|
|
iRatio = GetMaxWidthIndex(
|
|
tmp,
|
|
idx //
|
|
);
|
|
|
|
//
|
|
has = IsValidIndex(idx);
|
|
if (!has)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
has = iRatio > 0;
|
|
|
|
//
|
|
ArrayRemove(
|
|
tmp,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
bool canSetTP = tp <= 0;
|
|
|
|
//
|
|
iReward = iRatio * risk;
|
|
|
|
//
|
|
iRewardPrice =
|
|
isBullish
|
|
? entry + iReward
|
|
: entry - iReward;
|
|
if (canSetTP)
|
|
{
|
|
tp = iRewardPrice;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
iTarget.target = iRewardPrice;
|
|
AddRef(
|
|
iTarget,
|
|
targets //
|
|
);
|
|
|
|
//
|
|
iTarget.Clean();
|
|
}
|
|
}
|
|
Clean(tmp);
|
|
|
|
//
|
|
// Filling Signal ...
|
|
signal.tp = tp;
|
|
signal.sl = sl;
|
|
signal.type = iType;
|
|
signal.comment = "";
|
|
signal.entry = entry;
|
|
signal.time = box.to;
|
|
signal.volume = 0.01;
|
|
signal.provider = box.type;
|
|
signal.symbol = box.symbol;
|
|
signal.period = box.period;
|
|
signal.mode = X_ORDER_MODE_MARKET;
|
|
|
|
//
|
|
if (HasChild(targets))
|
|
{
|
|
//
|
|
Copy(
|
|
targets,
|
|
signal.targets //
|
|
);
|
|
}
|
|
|
|
//
|
|
result = signal.IsValid();
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
signal.Clean();
|
|
}
|
|
|
|
//
|
|
Clean(tmp);
|
|
Clean(targets);
|
|
iTarget.Clean();
|
|
entryBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts a Signal to Position ...
|
|
*
|
|
* @param signal: XSignal, reference to Specified Signal ...
|
|
* @param position: XPosition, reference to Generated Position ...
|
|
* @param magic: ulong, Specified Magic Number ...
|
|
* @param ticket: ulong, Specified Position Ticket ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToXPosition(
|
|
XSignal &signal,
|
|
XPosition &position,
|
|
ulong magic = 0,
|
|
ulong ticket = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
position.Clean();
|
|
|
|
//
|
|
// Validate ...
|
|
result = signal.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Normalize ...
|
|
|
|
//
|
|
if (ticket <= 0)
|
|
{
|
|
//
|
|
if (signal.positionId > 0)
|
|
{
|
|
ticket = signal.positionId;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
ticket = MathRand();
|
|
signal.positionId = ticket;
|
|
}
|
|
}
|
|
signal.positionId = ticket;
|
|
|
|
//
|
|
if (magic <= 0)
|
|
{
|
|
magic = MathRand();
|
|
}
|
|
|
|
//
|
|
// Filling Position ...
|
|
position.swap = 0;
|
|
position.profit = 0;
|
|
position.magic = magic;
|
|
position.commission = 0;
|
|
position.tp = signal.tp;
|
|
position.sl = signal.sl;
|
|
position.ticket = ticket;
|
|
position.type = signal.type;
|
|
position.price = signal.entry;
|
|
position.entry = signal.entry;
|
|
position.openAt = signal.time;
|
|
position.volume = signal.volume;
|
|
position.symbol = signal.symbol;
|
|
position.period = signal.period;
|
|
position.comment = signal.comment;
|
|
position.provider = signal.provider;
|
|
|
|
//
|
|
result = position.IsValid();
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
if (!result)
|
|
{
|
|
position.Clean();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Update Specified Position by Bar ...
|
|
*
|
|
* @param position: XPosition, reference to Specified Position ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool XUpdatePosition(
|
|
XPosition &position,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
|
|
//
|
|
// Validate ...
|
|
result = position.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL bar;
|
|
result = bar.Init(
|
|
position.symbol,
|
|
position.period,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double entryDiff = MathAbs(position.entry - position.price);
|
|
bool isLong = IsLong(position.type);
|
|
bool isInProfit = isLong
|
|
? position.price > position.entry
|
|
: position.price < position.entry;
|
|
bool isTargeted =
|
|
isLong
|
|
? position.price >= position.tp
|
|
: position.price <= position.tp;
|
|
bool isStoped =
|
|
isLong
|
|
? position.price <= position.sl
|
|
: position.price >= position.sl;
|
|
result = !isTargeted && !isStoped;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double spread = GetSpread(position.symbol);
|
|
position.price = bar.close +
|
|
(isLong
|
|
? spread
|
|
: (-1 * spread));
|
|
entryDiff = MathAbs(position.entry - position.price);
|
|
isInProfit = isLong
|
|
? position.price > position.entry
|
|
: position.price < position.entry;
|
|
result = position.IsValid();
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Implementation ...
|
|
|
|
//
|
|
// Global Chart Objects ...
|
|
|
|
/**
|
|
* Base Chart Object ...
|
|
**/
|
|
class XCBaseObject : public CChartObject
|
|
{
|
|
//
|
|
public:
|
|
//
|
|
|
|
//
|
|
// Getter(s) / Setter(s) ...
|
|
|
|
/**
|
|
* Get Object Specified Name ...
|
|
*
|
|
* @return ( string )
|
|
*/
|
|
string ObjName()
|
|
{
|
|
return mObjName;
|
|
}
|
|
|
|
/**
|
|
* Set Object Specified Name ...
|
|
*
|
|
* @param value: String ...
|
|
*/
|
|
void ObjName(string value)
|
|
{
|
|
//
|
|
Name(value);
|
|
mObjName = value;
|
|
}
|
|
|
|
virtual string TypeString()
|
|
{
|
|
return ToXString(X_EMPTY_OBJ);
|
|
}
|
|
|
|
/**
|
|
* Retrieve Object Type ...
|
|
*
|
|
* @return ( ENUM_XCHARTOBJECTS )
|
|
*/
|
|
virtual int Type(void) const
|
|
{
|
|
return ((int)X_EMPTY_OBJ);
|
|
}
|
|
|
|
/**
|
|
* Destroy ...
|
|
*/
|
|
void virtual Destroy()
|
|
{
|
|
//
|
|
Detach();
|
|
Delete();
|
|
}
|
|
|
|
//
|
|
private:
|
|
//
|
|
|
|
//
|
|
// Props ...
|
|
string mObjName; // Object Specified Name ...
|
|
|
|
//
|
|
};
|
|
|
|
/**
|
|
* Bar Arrow Object ...
|
|
**/
|
|
class XCBarArrowObject : public XCBaseObject
|
|
{
|
|
//
|
|
public:
|
|
//
|
|
|
|
/**
|
|
* Creator ...
|
|
*
|
|
* @param chart_id: Long, Specified Chart ID ...
|
|
* @param name: String, Specified Object ID ...
|
|
* @param window: Integer, Specified Chart Window ID ...
|
|
* @param swing: XCSwing instance ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool CreateByBar(
|
|
long chart_id,
|
|
string name,
|
|
int window,
|
|
int arrow,
|
|
XOHCL &bar,
|
|
ENUM_X_PRICE priceType,
|
|
double threshold = 5 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
bar.IsValid() &&
|
|
IsValid(name)
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
datetime time = bar.time;
|
|
double price = bar.GetPrice(priceType);
|
|
|
|
//
|
|
if (threshold > 0)
|
|
{
|
|
//
|
|
double thresholdPrice = threshold * GetPoints(bar.symbol);
|
|
if (priceType == X_PRICE_HIGH)
|
|
{
|
|
price += thresholdPrice;
|
|
}
|
|
else if (priceType == X_PRICE_LOW)
|
|
{
|
|
price -= thresholdPrice;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = mArrow.Create(
|
|
chart_id,
|
|
name,
|
|
window,
|
|
time,
|
|
price,
|
|
(char)arrow //
|
|
);
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
ObjName(name);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Virtual ...
|
|
|
|
/**
|
|
* Destroy ...
|
|
*/
|
|
void virtual Destroy()
|
|
{
|
|
//
|
|
mArrow.Detach();
|
|
mArrow.Delete();
|
|
|
|
//
|
|
Detach();
|
|
Delete();
|
|
}
|
|
|
|
/**
|
|
* Retrieve Object Type ...
|
|
*
|
|
* @return ( ENUM_XCHARTOBJECTS )
|
|
*/
|
|
virtual int Type(void)
|
|
{
|
|
return (int)X_BAR_ARROW_OBJ;
|
|
}
|
|
|
|
/**
|
|
* Type as String ...
|
|
**/
|
|
string TypeString() override
|
|
{
|
|
return ToXString(X_BAR_ARROW_OBJ);
|
|
}
|
|
|
|
//
|
|
// Setter(s) ...
|
|
|
|
/**
|
|
* Set Arrow Anchor ...
|
|
*
|
|
* @param value: ENUM_ARROW_ANCHOR member ...
|
|
*/
|
|
void ArrowAnchor(ENUM_ARROW_ANCHOR value)
|
|
{
|
|
mArrow.Anchor(value);
|
|
}
|
|
|
|
/**
|
|
* Set Arrow Color ...
|
|
*
|
|
* @param value: Color ...
|
|
*/
|
|
void ArrowColor(color value)
|
|
{
|
|
mArrow.Color(value);
|
|
}
|
|
|
|
/**
|
|
* Set Arrow Width ...
|
|
*
|
|
* @param value: Integer ...
|
|
*/
|
|
void ArrowWidth(int value)
|
|
{
|
|
mArrow.Width(value);
|
|
}
|
|
|
|
//
|
|
private:
|
|
//
|
|
CChartObjectArrow mArrow;
|
|
|
|
//
|
|
};
|
|
|
|
/**
|
|
* Signal Object ...
|
|
**/
|
|
class XCSignalObject : public XCBaseObject
|
|
{
|
|
//
|
|
public:
|
|
//
|
|
|
|
//
|
|
// Constructor ...
|
|
void XCSignalObject()
|
|
{
|
|
}
|
|
|
|
//
|
|
// Deconstructor ...
|
|
void ~XCSignalObject()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Create a Signal Object on Chart ...
|
|
*
|
|
* @param chart_id: Long ...
|
|
* @param name: String ...
|
|
* @param window: Integer ...
|
|
* @param signal: XSignal instance ...
|
|
* @param length: int, Specified Length of Signal ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Create(
|
|
long chart_id,
|
|
const int window,
|
|
XSignal &signal,
|
|
int length = 3,
|
|
string prefix = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
length = NormalizeInt(length, 3);
|
|
|
|
//
|
|
result = signal.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string name = signal.GetTag();
|
|
if (IsValid(prefix))
|
|
{
|
|
name = prefix + "_" + name;
|
|
}
|
|
string nameMD5 = ToMD5(name);
|
|
|
|
//
|
|
int delay = (PeriodSeconds(signal.period) * length);
|
|
datetime time1 = (datetime)((int)signal.time - delay);
|
|
datetime time2 = (datetime)((int)signal.time + delay);
|
|
|
|
//
|
|
// TP ...
|
|
string tpName = ToString(X_TP) + "_" + nameMD5;
|
|
result = mTPTrend.Create(
|
|
chart_id,
|
|
tpName,
|
|
window,
|
|
time1,
|
|
signal.tp,
|
|
time2,
|
|
signal.tp //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// SL ...
|
|
string slName = ToString(X_SL) + "_" + nameMD5;
|
|
result = mSLTrend.Create(
|
|
chart_id,
|
|
slName,
|
|
window,
|
|
time1,
|
|
signal.sl,
|
|
time2,
|
|
signal.sl //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
mTPTrend.Delete();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// TARGET ...
|
|
bool hasTargets = HasChild(signal.targets);
|
|
if (hasTargets)
|
|
{
|
|
//
|
|
int targetsCount = ArraySize(signal.targets);
|
|
for (int i = 0; i < targetsCount; i++)
|
|
{
|
|
//
|
|
string targetName = ToString(X_TARGET) + "_" + ToXString(i) + "_" + nameMD5;
|
|
CChartObjectTrend *mTargetTrend;
|
|
mTargetTrend = new CChartObjectTrend();
|
|
result = mTargetTrend.Create(
|
|
chart_id,
|
|
targetName,
|
|
window,
|
|
time1,
|
|
signal.targets[i].target,
|
|
time2,
|
|
signal.targets[i].target //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
mTPTrend.Delete();
|
|
mSLTrend.Delete();
|
|
break;
|
|
}
|
|
|
|
//
|
|
mTargetTrends.Add(mTargetTrend);
|
|
}
|
|
}
|
|
|
|
//
|
|
// ENTRY ...
|
|
string entrName = ToString(X_ENTRY) + "_" + nameMD5;
|
|
result = mEntryTrend.Create(
|
|
chart_id,
|
|
entrName,
|
|
window,
|
|
time1,
|
|
signal.entry,
|
|
time2,
|
|
signal.entry //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
mTPTrend.Delete();
|
|
mSLTrend.Delete();
|
|
mTargetTrends.Clear();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Set Object Name ...
|
|
ObjName(name);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Virtual ...
|
|
|
|
/**
|
|
* Destroy ...
|
|
*/
|
|
void virtual Destroy()
|
|
{
|
|
//
|
|
mTPTrend.Detach();
|
|
mTPTrend.Delete();
|
|
mSLTrend.Detach();
|
|
mSLTrend.Delete();
|
|
mEntryTrend.Detach();
|
|
mEntryTrend.Delete();
|
|
|
|
//
|
|
mTargetTrends.Clear();
|
|
|
|
//
|
|
Detach();
|
|
Delete();
|
|
}
|
|
|
|
/**
|
|
* Retrieve Object Type ...
|
|
*
|
|
* @return ( ENUM_XCHARTOBJECTS )
|
|
*/
|
|
virtual int Type(void)
|
|
{
|
|
return (int)X_SIGNAL_OBJ;
|
|
}
|
|
|
|
/**
|
|
* Type as String ...
|
|
**/
|
|
string TypeString() override
|
|
{
|
|
return ToXString(X_SIGNAL_OBJ);
|
|
}
|
|
|
|
//
|
|
// Setter(s) ...
|
|
|
|
//
|
|
// TP ...
|
|
|
|
/**
|
|
* Set TP Width ...
|
|
*
|
|
* @param value: Integer ...
|
|
*/
|
|
void TPWidth(int value)
|
|
{
|
|
//
|
|
if (value < 1)
|
|
{
|
|
value = 1;
|
|
}
|
|
|
|
//
|
|
mTPTrend.Width(value);
|
|
}
|
|
|
|
/**
|
|
* Set TP Color ...
|
|
*
|
|
* @param value: Color ...
|
|
*/
|
|
void TPColor(color value)
|
|
{
|
|
mTPTrend.Color(value);
|
|
}
|
|
|
|
/**
|
|
* Set TP Style ...
|
|
*
|
|
* @param value: ENUM_LINE_STYLE ...
|
|
*/
|
|
void TPStyle(ENUM_LINE_STYLE value)
|
|
{
|
|
mTPTrend.Style(value);
|
|
}
|
|
|
|
//
|
|
// SL ...
|
|
|
|
/**
|
|
* Set SL Width ...
|
|
*
|
|
* @param value: Integer ...
|
|
*/
|
|
void SLWidth(int value)
|
|
{
|
|
//
|
|
if (value < 1)
|
|
{
|
|
value = 1;
|
|
}
|
|
|
|
//
|
|
mSLTrend.Width(value);
|
|
}
|
|
|
|
/**
|
|
* Set SL Color ...
|
|
*
|
|
* @param value: Color ...
|
|
*/
|
|
void SLColor(color value)
|
|
{
|
|
mSLTrend.Color(value);
|
|
}
|
|
|
|
/**
|
|
* Set SL Style ...
|
|
*
|
|
* @param value: ENUM_LINE_STYLE ...
|
|
*/
|
|
void SLStyle(ENUM_LINE_STYLE value)
|
|
{
|
|
mSLTrend.Style(value);
|
|
}
|
|
|
|
//
|
|
// TARGET ...
|
|
|
|
/**
|
|
* Set Target Width ...
|
|
*
|
|
* @param value: Integer ...
|
|
*/
|
|
void TargetWidth(int value)
|
|
{
|
|
//
|
|
if (value < 1)
|
|
{
|
|
value = 1;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < mTargetTrends.Total(); i++)
|
|
{
|
|
//
|
|
CChartObjectTrend *iTrend = (CChartObjectTrend *)mTargetTrends.At(i);
|
|
iTrend.Width(value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set Target Color ...
|
|
*
|
|
* @param value: Color ...
|
|
*/
|
|
void TargetColor(color value)
|
|
{
|
|
//
|
|
for (int i = 0; i < mTargetTrends.Total(); i++)
|
|
{
|
|
//
|
|
CChartObjectTrend *iTrend = (CChartObjectTrend *)mTargetTrends.At(i);
|
|
iTrend.Color(value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set Target Style ...
|
|
*
|
|
* @param value: ENUM_LINE_STYLE ...
|
|
*/
|
|
void TargetStyle(ENUM_LINE_STYLE value)
|
|
{
|
|
//
|
|
for (int i = 0; i < mTargetTrends.Total(); i++)
|
|
{
|
|
//
|
|
CChartObjectTrend *iTrend = (CChartObjectTrend *)mTargetTrends.At(i);
|
|
iTrend.Style(value);
|
|
}
|
|
}
|
|
|
|
//
|
|
// ENTRY ...
|
|
|
|
/**
|
|
* Set Entry Width ...
|
|
*
|
|
* @param value: Integer ...
|
|
*/
|
|
void EntryWidth(int value)
|
|
{
|
|
//
|
|
if (value < 1)
|
|
{
|
|
value = 1;
|
|
}
|
|
|
|
//
|
|
mEntryTrend.Width(value);
|
|
}
|
|
|
|
/**
|
|
* Set Entry Color ...
|
|
*
|
|
* @param value: Color ...
|
|
*/
|
|
void EntryColor(color value)
|
|
{
|
|
mEntryTrend.Color(value);
|
|
}
|
|
|
|
/**
|
|
* Set Entry Style ...
|
|
*
|
|
* @param value: ENUM_LINE_STYLE ...
|
|
*/
|
|
void EntryStyle(ENUM_LINE_STYLE value)
|
|
{
|
|
mEntryTrend.Style(value);
|
|
}
|
|
|
|
//
|
|
private:
|
|
//
|
|
|
|
//
|
|
CChartObjectTrend mTPTrend;
|
|
CChartObjectTrend mSLTrend;
|
|
CChartObjectTrend mEntryTrend;
|
|
CArrayObj mTargetTrends;
|
|
};
|
|
|
|
/**
|
|
* XRR Object ...
|
|
**/
|
|
class XCRRObject : public XCSignalObject
|
|
{
|
|
//
|
|
// Public ...
|
|
public:
|
|
//
|
|
// Constructor ...
|
|
bool CreateBoxRR(
|
|
long chart_id,
|
|
const int window,
|
|
XBoxZone &box,
|
|
double &rewardRatios[],
|
|
int length = 3,
|
|
string prefix = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
length = NormalizeInt(length, 3);
|
|
|
|
//
|
|
result = box.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XSignal signal;
|
|
result = ToXSignal(
|
|
box,
|
|
signal,
|
|
rewardRatios //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
signal.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = Create(
|
|
chart_id,
|
|
window,
|
|
signal,
|
|
length,
|
|
prefix //
|
|
);
|
|
|
|
//
|
|
signal.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieve Object Type ...
|
|
*
|
|
* @return ( ENUM_XCHARTOBJECTS )
|
|
*/
|
|
virtual int Type(void)
|
|
{
|
|
return (int)X_RR_OBJ;
|
|
}
|
|
|
|
/**
|
|
* Type as String ...
|
|
**/
|
|
string TypeString() override
|
|
{
|
|
return ToXString(X_RR_OBJ);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* XOHCL Object ...
|
|
**/
|
|
class XCOHCLObject : public XCBaseObject
|
|
{
|
|
//
|
|
public:
|
|
//
|
|
|
|
/**
|
|
* Creator ...
|
|
*
|
|
* @param chart_id: Long, Specified Chart ID ...
|
|
* @param window: Integer, Specified Chart Window ID ...
|
|
* @param pivot: XPVPivot instance ...
|
|
* @param prefix: String ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Create(
|
|
long chart_id,
|
|
int window,
|
|
XOHCL &bar,
|
|
datetime to,
|
|
string prefix = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = bar.IsValid() &&
|
|
IsValid(to);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string name = bar.GetTag();
|
|
if (IsValid(prefix))
|
|
{
|
|
name = prefix + "_" + name;
|
|
}
|
|
string nameMD5 = ToMD5(name);
|
|
|
|
//
|
|
// High Shadow ...
|
|
string hShadowName = ToString(X_BAR_H_SHW) + "_" + nameMD5;
|
|
|
|
//
|
|
result = mHighShadowRect.Create(
|
|
chart_id,
|
|
hShadowName,
|
|
window,
|
|
bar.time,
|
|
bar.high,
|
|
to,
|
|
bar.GetUp() //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Body ...
|
|
string bodyName = ToString(X_BAR_BDY) + "_" + nameMD5;
|
|
|
|
//
|
|
result = mBodyRect.Create(
|
|
chart_id,
|
|
bodyName,
|
|
window,
|
|
bar.time,
|
|
bar.GetUp(),
|
|
to,
|
|
bar.GetDown() //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
mHighShadowRect.Delete();
|
|
mHighShadowRect.Detach();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Low Shadow ...
|
|
string lShadowName = ToString(X_BAR_L_SHW) + "_" + nameMD5;
|
|
|
|
//
|
|
result = mLowShadowRect.Create(
|
|
chart_id,
|
|
lShadowName,
|
|
window,
|
|
bar.time,
|
|
bar.GetDown(),
|
|
to,
|
|
bar.low //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
mBodyRect.Delete();
|
|
mBodyRect.Detach();
|
|
mHighShadowRect.Delete();
|
|
mHighShadowRect.Detach();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
ObjName(name);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Virtual ...
|
|
|
|
/**
|
|
* Destroy ...
|
|
*/
|
|
void virtual Destroy()
|
|
{
|
|
//
|
|
mBodyRect.Detach();
|
|
mBodyRect.Delete();
|
|
|
|
//
|
|
mLowShadowRect.Detach();
|
|
mLowShadowRect.Delete();
|
|
|
|
//
|
|
mHighShadowRect.Detach();
|
|
mHighShadowRect.Delete();
|
|
|
|
//
|
|
Detach();
|
|
Delete();
|
|
}
|
|
|
|
/**
|
|
* Retrieve Object Type ...
|
|
*
|
|
* @return ( ENUM_XCHARTOBJECTS )
|
|
*/
|
|
virtual int Type(void)
|
|
{
|
|
return (int)X_OHCL_OBJ;
|
|
}
|
|
|
|
/**
|
|
* Type as String ...
|
|
**/
|
|
string TypeString() override
|
|
{
|
|
return ToXString(X_OHCL_OBJ);
|
|
}
|
|
|
|
//
|
|
// Getter(s) / Setter(s) ...
|
|
|
|
/**
|
|
* Set High Shadow Width ...
|
|
*
|
|
* @param value: Integer ...
|
|
*/
|
|
void HighShadowWidth(int value)
|
|
{
|
|
//
|
|
if (value < 1)
|
|
{
|
|
value = 1;
|
|
}
|
|
|
|
//
|
|
mHighShadowRect.Width(value);
|
|
}
|
|
|
|
/**
|
|
* Set High Shadow Color ...
|
|
*
|
|
* @param value: Color ...
|
|
*/
|
|
void HighShadowColor(color value)
|
|
{
|
|
mHighShadowRect.Color(value);
|
|
}
|
|
|
|
/**
|
|
* Set High Shadow Style ...
|
|
*
|
|
* @param value: ENUM_LINE_STYLE member ...
|
|
*/
|
|
void HighShadowStyle(ENUM_LINE_STYLE value)
|
|
{
|
|
mHighShadowRect.Style(value);
|
|
}
|
|
|
|
/**
|
|
* Set High Shadow Fill ...
|
|
*
|
|
* @param value: Boolean ...
|
|
*/
|
|
void HighShadowFill(bool value)
|
|
{
|
|
mHighShadowRect.Fill(value);
|
|
}
|
|
|
|
/**
|
|
* Set Body Width ...
|
|
*
|
|
* @param value: Integer ...
|
|
*/
|
|
void BodyWidth(int value)
|
|
{
|
|
//
|
|
if (value < 1)
|
|
{
|
|
value = 1;
|
|
}
|
|
|
|
//
|
|
mBodyRect.Width(value);
|
|
}
|
|
|
|
/**
|
|
* Set Body Color ...
|
|
*
|
|
* @param value: Color ...
|
|
*/
|
|
void BodyColor(color value)
|
|
{
|
|
mBodyRect.Color(value);
|
|
}
|
|
|
|
/**
|
|
* Set Body Style ...
|
|
*
|
|
* @param value: ENUM_LINE_STYLE member ...
|
|
*/
|
|
void BodyStyle(ENUM_LINE_STYLE value)
|
|
{
|
|
mBodyRect.Style(value);
|
|
}
|
|
|
|
/**
|
|
* Set Body Fill ...
|
|
*
|
|
* @param value: Boolean ...
|
|
*/
|
|
void BodyFill(bool value)
|
|
{
|
|
mBodyRect.Fill(value);
|
|
}
|
|
|
|
/**
|
|
* Set Low Shadow Width ...
|
|
*
|
|
* @param value: Integer ...
|
|
*/
|
|
void LowShadowWidth(int value)
|
|
{
|
|
//
|
|
if (value < 1)
|
|
{
|
|
value = 1;
|
|
}
|
|
|
|
//
|
|
mLowShadowRect.Width(value);
|
|
}
|
|
|
|
/**
|
|
* Set Low Shadow Color ...
|
|
*
|
|
* @param value: Color ...
|
|
*/
|
|
void LowShadowColor(color value)
|
|
{
|
|
mLowShadowRect.Color(value);
|
|
}
|
|
|
|
/**
|
|
* Set Low Shadow Style ...
|
|
*
|
|
* @param value: ENUM_LINE_STYLE member ...
|
|
*/
|
|
void LowShadowStyle(ENUM_LINE_STYLE value)
|
|
{
|
|
mLowShadowRect.Style(value);
|
|
}
|
|
|
|
/**
|
|
* Set Low Shadow Fill ...
|
|
*
|
|
* @param value: Boolean ...
|
|
*/
|
|
void LowShadowFill(bool value)
|
|
{
|
|
mLowShadowRect.Fill(value);
|
|
}
|
|
|
|
void BarSpes(
|
|
int width = 1,
|
|
color clr = clrNONE,
|
|
ENUM_LINE_STYLE style = STYLE_SOLID,
|
|
bool fill = false //
|
|
)
|
|
{
|
|
//
|
|
BodyWidth(width);
|
|
LowShadowWidth(width);
|
|
HighShadowWidth(width);
|
|
|
|
//
|
|
BodyColor(clr);
|
|
LowShadowColor(clr);
|
|
HighShadowColor(clr);
|
|
|
|
//
|
|
BodyStyle(style);
|
|
LowShadowStyle(style);
|
|
HighShadowStyle(style);
|
|
|
|
//
|
|
BodyFill(fill);
|
|
LowShadowFill(fill);
|
|
HighShadowFill(fill);
|
|
}
|
|
|
|
//
|
|
private:
|
|
//
|
|
|
|
//
|
|
// Props ...
|
|
CChartObjectRectangle mHighShadowRect;
|
|
CChartObjectRectangle mBodyRect;
|
|
CChartObjectRectangle mLowShadowRect;
|
|
};
|
|
|
|
/**
|
|
* Box Object ...
|
|
**/
|
|
class XCBoxObject : public XCBaseObject
|
|
{
|
|
//
|
|
public:
|
|
//
|
|
|
|
/**
|
|
* Creator ...
|
|
*
|
|
* @param chart_id: Long, Specified Chart ID ...
|
|
* @param window: Integer, Specified Chart Window ID ...
|
|
* @param pivot: XPVPivot instance ...
|
|
* @param prefix: String ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Create(
|
|
long chart_id,
|
|
int window,
|
|
string name,
|
|
double upper,
|
|
double lower,
|
|
datetime from,
|
|
datetime to,
|
|
datetime at = NULL,
|
|
string prefix = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
upper > 0 &&
|
|
lower > 0 &&
|
|
to > from &&
|
|
IsValid(to) &&
|
|
IsValid(name) &&
|
|
IsValid(from) &&
|
|
upper > lower;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (IsValid(prefix))
|
|
{
|
|
name = prefix + "_" + name;
|
|
}
|
|
string nameMD5 = ToMD5(name);
|
|
|
|
//
|
|
result = mRect.Create(
|
|
chart_id,
|
|
name,
|
|
window,
|
|
from,
|
|
upper,
|
|
to,
|
|
lower //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
if (IsValid(at))
|
|
{
|
|
//
|
|
result = mAt.Create(
|
|
chart_id,
|
|
name + ToString(X_AT),
|
|
window,
|
|
at //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
//
|
|
mAt.Detach();
|
|
mAt.Delete();
|
|
|
|
//
|
|
mRect.Detach();
|
|
mRect.Delete();
|
|
}
|
|
}
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
ObjName(name);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Virtual ...
|
|
|
|
/**
|
|
* Destroy ...
|
|
*/
|
|
void virtual Destroy()
|
|
{
|
|
//
|
|
mAt.Detach();
|
|
mAt.Delete();
|
|
|
|
//
|
|
mRect.Detach();
|
|
mRect.Delete();
|
|
|
|
//
|
|
Detach();
|
|
Delete();
|
|
}
|
|
|
|
/**
|
|
* Retrieve Object Type ...
|
|
*
|
|
* @return ( ENUM_XCHARTOBJECTS )
|
|
*/
|
|
virtual int Type(void)
|
|
{
|
|
return (int)X_BOX_OBJ;
|
|
}
|
|
|
|
/**
|
|
* Type as String ...
|
|
**/
|
|
string TypeString() override
|
|
{
|
|
return ToXString(X_BOX_OBJ);
|
|
}
|
|
|
|
//
|
|
// Getter(s) / Setter(s) ...
|
|
|
|
/**
|
|
* Set Width ...
|
|
*
|
|
* @param value: Integer ...
|
|
*/
|
|
void BoxWidth(int value)
|
|
{
|
|
//
|
|
if (value < 1)
|
|
{
|
|
value = 1;
|
|
}
|
|
|
|
//
|
|
mAt.Width(value);
|
|
mRect.Width(value);
|
|
}
|
|
|
|
/**
|
|
* Set Color ...
|
|
*
|
|
* @param value: Color ...
|
|
*/
|
|
void BoxColor(color value)
|
|
{
|
|
//
|
|
mAt.Color(value);
|
|
mRect.Color(value);
|
|
}
|
|
|
|
/**
|
|
* Set Style ...
|
|
*
|
|
* @param value: ENUM_LINE_STYLE member ...
|
|
*/
|
|
void BoxStyle(ENUM_LINE_STYLE value)
|
|
{
|
|
//
|
|
mAt.Style(value);
|
|
mRect.Style(value);
|
|
}
|
|
|
|
/**
|
|
* Set Fill ...
|
|
*
|
|
* @param value: Boolean ...
|
|
*/
|
|
void BoxFill(bool value)
|
|
{
|
|
mRect.Fill(value);
|
|
}
|
|
|
|
//
|
|
private:
|
|
//
|
|
|
|
//
|
|
// Props ...
|
|
CChartObjectVLine mAt;
|
|
CChartObjectRectangle mRect;
|
|
};
|
|
|
|
/**
|
|
* Position Object ...
|
|
**/
|
|
class XCPositionObject : public XCBaseObject
|
|
{
|
|
//
|
|
// Public ...
|
|
public:
|
|
//
|
|
XPOIStyle riskStyle; // Risk Box Style ...
|
|
color inProfitColor; // In Profit Price Box Color ...
|
|
color inDrawdownColor; // In Drawdown Price Box Color ...
|
|
XPOIStyle rewardStyle; // Reward Box Style ...
|
|
ENUM_LINE_STYLE priceStyle; // Price Box Style ...
|
|
|
|
//
|
|
// Creators ...
|
|
|
|
/**
|
|
* Create a Position Object by Signal reference ...
|
|
*
|
|
* @param chart_id: Long, Specified Chart ID ...
|
|
* @param window: Integer, Specified Chart Window ID ...
|
|
* @param signal: XSignal, reference to Provided Signal ...
|
|
* @param magic: ulong, Specified Position Magic Number ...
|
|
* @param ticket: ulong, Specified Position Ticket ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Create(
|
|
long chart_id,
|
|
int window,
|
|
XSignal &signal,
|
|
ulong magic = 0,
|
|
ulong ticket = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Converts Signal to Test Position ...
|
|
XPosition _position;
|
|
result = ToXPosition(
|
|
signal,
|
|
_position,
|
|
magic,
|
|
ticket //
|
|
);
|
|
|
|
//
|
|
// Validate ...
|
|
result = chart_id >= 0 &&
|
|
window >= 0 &&
|
|
_position.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = Create(
|
|
chart_id,
|
|
window,
|
|
_position //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Create a Position Object ...
|
|
*
|
|
* @param chart_id: Long, Specified Chart ID ...
|
|
* @param window: Integer, Specified Chart Window ID ...
|
|
* @param position: XPosition, reference to Specified Position ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Create(
|
|
long chart_id,
|
|
int window,
|
|
XPosition &position //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate ...
|
|
result = chart_id >= 0 &&
|
|
window >= 0 &&
|
|
position.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = Update(position);
|
|
if (!result)
|
|
{
|
|
//
|
|
Destroy();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Update Position if Belongs to ...
|
|
*
|
|
* @param position: XPosition, reference to Specified Position ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Update(
|
|
XPosition &position,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
|
|
//
|
|
// Validate ...
|
|
result =
|
|
mChartID >= 0 &&
|
|
mWindowID >= 0 &&
|
|
position.IsValid() &&
|
|
(!HasPosition()
|
|
? true
|
|
: IsBelong(position));
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
datetime _toTime = GetBarTime(
|
|
position.symbol,
|
|
position.period,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
// Validate Chart Info ...
|
|
result = UpdatePosition(
|
|
position,
|
|
_toTime //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Update Position if Belongs to ...
|
|
*
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Update(int barIndex = 0)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
|
|
//
|
|
// Validate ...
|
|
result = HasPosition();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Update mPosition ...
|
|
result = XUpdatePosition(mPosition, barIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = Update(
|
|
mPosition,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrievers ...
|
|
|
|
bool GetPosition(XPosition &_position)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare ...
|
|
_position.Clean();
|
|
|
|
//
|
|
// Validate ...
|
|
result = HasPosition();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
_position = mPosition;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Checkers ...
|
|
|
|
/**
|
|
* Check Object is Belongs to Specified Position or not ...
|
|
*
|
|
* @param position: XPosition, reference to Specified Position ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBelong(XPosition &position)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate ...
|
|
result =
|
|
HasPosition() &&
|
|
position.IsValid();
|
|
|
|
//
|
|
// Check ...
|
|
result =
|
|
result &&
|
|
mPosition.ticket == position.ticket;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Overrides ...
|
|
|
|
/**
|
|
* Retrieve Object Type ...
|
|
*
|
|
* @return ( ENUM_XCHARTOBJECTS )
|
|
*/
|
|
string TypeString() override
|
|
{
|
|
return ToXString(X_POSITION_OBJ);
|
|
}
|
|
|
|
/**
|
|
* Retrieve Object Type ...
|
|
*
|
|
* @return ( ENUM_XCHARTOBJECTS )
|
|
*/
|
|
int Type(void) const override
|
|
{
|
|
return ((int)X_POSITION_OBJ);
|
|
}
|
|
|
|
/**
|
|
* Destroy Object ...
|
|
**/
|
|
void Destroy() override
|
|
{
|
|
//
|
|
ObjName(NULL);
|
|
|
|
//
|
|
mRiskBox.Clean();
|
|
mPosition.Clean();
|
|
mPriceBox.Clean();
|
|
mRewardBox.Clean();
|
|
|
|
//
|
|
mRiskBoxObj.Detach();
|
|
mRiskBoxObj.Delete();
|
|
|
|
//
|
|
mPriceBoxObj.Detach();
|
|
mPriceBoxObj.Delete();
|
|
|
|
//
|
|
mRewardBoxObj.Detach();
|
|
mRewardBoxObj.Delete();
|
|
}
|
|
|
|
//
|
|
// Stylers ...
|
|
|
|
/**
|
|
* Apply Styles based on Current Style Configurations ...
|
|
*/
|
|
void ApplyStyle()
|
|
{
|
|
//
|
|
// Validate ...
|
|
bool has = HasPosition();
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Check Position in Profit ...
|
|
bool isLong = IsLong(mPosition.type);
|
|
bool isRiskFreed =
|
|
isLong
|
|
? mPosition.sl > mPosition.entry
|
|
: mPosition.sl < mPosition.entry;
|
|
bool isInProfit = mPosition.profit > 0;
|
|
XPOIStyle _priceStyle;
|
|
if (isInProfit)
|
|
{
|
|
//
|
|
_priceStyle = rewardStyle;
|
|
_priceStyle.clr = inProfitColor;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
_priceStyle = riskStyle;
|
|
_priceStyle.clr = inDrawdownColor;
|
|
}
|
|
|
|
//
|
|
// Apply Profit Based Styles ...
|
|
_priceStyle.fill = true;
|
|
_priceStyle.style = priceStyle;
|
|
|
|
//
|
|
// Change Risk Style if Risk Freed Position ...
|
|
if (isRiskFreed) {
|
|
//
|
|
riskStyle.fill = true;
|
|
riskStyle.clr = rewardStyle.clr;
|
|
}
|
|
|
|
//
|
|
// Risk Style ...
|
|
mRiskBoxObj.BoxColor(riskStyle.clr);
|
|
mRiskBoxObj.BoxFill(riskStyle.fill);
|
|
mRiskBoxObj.BoxStyle(riskStyle.style);
|
|
mRiskBoxObj.BoxWidth(riskStyle.width);
|
|
|
|
//
|
|
// Reward Style ...
|
|
mRewardBoxObj.BoxColor(rewardStyle.clr);
|
|
mRewardBoxObj.BoxFill(rewardStyle.fill);
|
|
mRewardBoxObj.BoxStyle(rewardStyle.style);
|
|
mRewardBoxObj.BoxWidth(rewardStyle.width);
|
|
|
|
//
|
|
// Price Style ..
|
|
mPriceBoxObj.BoxColor(_priceStyle.clr);
|
|
mPriceBoxObj.BoxFill(_priceStyle.fill);
|
|
mPriceBoxObj.BoxStyle(_priceStyle.style);
|
|
mPriceBoxObj.BoxWidth(_priceStyle.width);
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
_priceStyle.Clean();
|
|
}
|
|
|
|
//
|
|
void ApplyStyle(
|
|
XPOIStyle &bullishStyle,
|
|
XPOIStyle &bearishStyle //
|
|
)
|
|
{
|
|
//
|
|
// Validate ...
|
|
if (!HasPosition())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Risk Box ...
|
|
if (mRiskBox.IsValid())
|
|
{
|
|
//
|
|
mRiskBoxObj.BoxColor(bearishStyle.clr);
|
|
mRiskBoxObj.BoxFill(bearishStyle.fill);
|
|
mRiskBoxObj.BoxStyle(bearishStyle.style);
|
|
mRiskBoxObj.BoxWidth(bearishStyle.width);
|
|
}
|
|
|
|
//
|
|
// Reward Box ...
|
|
if (mRewardBox.IsValid())
|
|
{
|
|
//
|
|
mRewardBoxObj.BoxColor(bullishStyle.clr);
|
|
mRewardBoxObj.BoxFill(bullishStyle.fill);
|
|
mRewardBoxObj.BoxStyle(bullishStyle.style);
|
|
mRewardBoxObj.BoxWidth(bullishStyle.width);
|
|
}
|
|
|
|
//
|
|
// Price Box ...
|
|
if (mPriceBox.IsValid())
|
|
{
|
|
//
|
|
XPOIStyle _priceStyle;
|
|
if (mPriceBox.IsBullish())
|
|
{
|
|
_priceStyle = bullishStyle;
|
|
}
|
|
else
|
|
{
|
|
_priceStyle = bearishStyle;
|
|
}
|
|
|
|
//
|
|
mPriceBoxObj.BoxColor(_priceStyle.clr);
|
|
mPriceBoxObj.BoxFill(_priceStyle.fill);
|
|
mPriceBoxObj.BoxStyle(_priceStyle.style);
|
|
mPriceBoxObj.BoxWidth(_priceStyle.width);
|
|
|
|
//
|
|
_priceStyle.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Protected ...
|
|
protected:
|
|
//
|
|
|
|
//
|
|
bool HasPosition()
|
|
{
|
|
return mPosition.IsValid();
|
|
}
|
|
|
|
//
|
|
bool UpdatePosition(
|
|
XPosition &_position,
|
|
datetime _toTime = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
_toTime = NormalizeTime(_toTime);
|
|
|
|
//
|
|
// Validate ...
|
|
result = _position.IsValid() &&
|
|
(!HasPosition()
|
|
? true
|
|
: _position.ticket == mPosition.ticket //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
mPosition = _position;
|
|
result = UpdateZones(_toTime);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool UpdateZones(datetime _toTime = NULL)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
_toTime = NormalizeTime(_toTime);
|
|
|
|
//
|
|
// Validate ...
|
|
result = HasPosition();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string iSymbol = mPosition.symbol;
|
|
ENUM_TIMEFRAMES iPeriod = mPosition.period;
|
|
|
|
//
|
|
datetime iAt = mPosition.openAt;
|
|
datetime iFrom = mPosition.openAt;
|
|
|
|
//
|
|
datetime _defaultToTime = iFrom + (PeriodSeconds(iPeriod) * 3);
|
|
datetime iTo = _toTime <= _defaultToTime
|
|
? _defaultToTime
|
|
: _toTime;
|
|
|
|
//
|
|
double iTP = mPosition.tp;
|
|
double iSL = mPosition.sl;
|
|
double iEntry = mPosition.entry;
|
|
double iPrice = mPosition.price;
|
|
|
|
//
|
|
bool isLong = IsLong(mPosition.type);
|
|
ENUM_X_DIRECTION iRiskDir = isLong
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_BULLISH;
|
|
ENUM_X_DIRECTION iRewardDir = isLong
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
bool isInProfit = mPosition.profit > 0;
|
|
bool isRiskFreed =
|
|
isLong
|
|
? mPosition.sl > mPosition.entry
|
|
: mPosition.sl < mPosition.entry;
|
|
ENUM_X_DIRECTION iPriceDir = isInProfit
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
// Try to Update Zones ...
|
|
string iSuffix = ToXString(mPosition.type) + "_" + ToXString(mPosition.ticket);
|
|
string iPrefix = ToXString(TimeToSeconds(mPosition.openAt));
|
|
string iName = iSuffix + "_" + iPrefix;
|
|
string iRiskName = iSuffix + "_" + "RISK" + "_" + iPrefix;
|
|
string iPriceName = iSuffix + "_" + "PRICE" + "_" + iPrefix;
|
|
string iRewardName = iSuffix + "_" + "REWARD" + "_" + iPrefix;
|
|
|
|
//
|
|
// Risk Box ...
|
|
mRiskBox.to = iTo;
|
|
mRiskBox.at = iAt;
|
|
mRiskBox.lower =
|
|
isLong
|
|
? isRiskFreed
|
|
? iEntry
|
|
: iSL
|
|
: isRiskFreed
|
|
? iSL
|
|
: iEntry;
|
|
mRiskBox.upper =
|
|
isLong
|
|
? isRiskFreed
|
|
? iSL
|
|
: iEntry
|
|
: isRiskFreed
|
|
? iEntry
|
|
: iSL;
|
|
mRiskBox.from = iFrom;
|
|
mRiskBox.symbol = iSymbol;
|
|
mRiskBox.period = iPeriod;
|
|
mRiskBox.type = iRiskName;
|
|
mRiskBox.dir = isRiskFreed
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
// Reward Box ...
|
|
mRewardBox.to = iTo;
|
|
mRewardBox.at = iAt;
|
|
mRewardBox.lower =
|
|
isLong
|
|
? iEntry
|
|
: iTP;
|
|
mRewardBox.upper =
|
|
isLong
|
|
? iTP
|
|
: iEntry;
|
|
mRewardBox.from = iFrom;
|
|
mRewardBox.symbol = iSymbol;
|
|
mRewardBox.period = iPeriod;
|
|
mRewardBox.type = iRewardName;
|
|
mRewardBox.dir = X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
// Price Box ...
|
|
mPriceBox.to = iTo;
|
|
mPriceBox.at = iAt;
|
|
mPriceBox.lower =
|
|
isLong
|
|
? isInProfit
|
|
? isRiskFreed
|
|
? iSL
|
|
: iEntry
|
|
: iPrice
|
|
: isInProfit
|
|
? isRiskFreed
|
|
? iSL
|
|
: iPrice
|
|
: iEntry;
|
|
mPriceBox.upper =
|
|
isLong
|
|
? isInProfit
|
|
? iPrice
|
|
: iEntry
|
|
: isInProfit
|
|
? iEntry
|
|
: iPrice;
|
|
mPriceBox.from = iFrom;
|
|
mPriceBox.symbol = iSymbol;
|
|
mPriceBox.period = iPeriod;
|
|
mPriceBox.type = iPriceName;
|
|
mPriceBox.dir = isInProfit
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
result = mRiskBox.IsValid() &&
|
|
mPriceBox.IsValid() &&
|
|
mRewardBox.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
mRiskBoxObj.Detach();
|
|
mRiskBoxObj.Delete();
|
|
bool isRiskCreated =
|
|
mRiskBoxObj.Create(
|
|
mChartID,
|
|
mWindowID,
|
|
mRiskBox.type,
|
|
mRiskBox.upper,
|
|
mRiskBox.lower,
|
|
mRiskBox.from,
|
|
mRiskBox.to,
|
|
NULL, // At ...
|
|
NULL // Prefix ...
|
|
);
|
|
|
|
//
|
|
mRewardBoxObj.Detach();
|
|
mRewardBoxObj.Delete();
|
|
bool isRewardCreated =
|
|
mRewardBoxObj.Create(
|
|
mChartID,
|
|
mWindowID,
|
|
mRewardBox.type,
|
|
mRewardBox.upper,
|
|
mRewardBox.lower,
|
|
mRewardBox.from,
|
|
mRewardBox.to,
|
|
NULL, // At ...
|
|
NULL // Prefix ...
|
|
);
|
|
|
|
//
|
|
mPriceBoxObj.Detach();
|
|
mPriceBoxObj.Delete();
|
|
bool isPriceCreated =
|
|
mPriceBoxObj.Create(
|
|
mChartID,
|
|
mWindowID,
|
|
mPriceBox.type,
|
|
mPriceBox.upper,
|
|
mPriceBox.lower,
|
|
mPriceBox.from,
|
|
mPriceBox.to,
|
|
NULL, // At ...
|
|
NULL // Prefix ...
|
|
);
|
|
|
|
//
|
|
result =
|
|
isRiskCreated &&
|
|
isPriceCreated &&
|
|
isRewardCreated;
|
|
if (result)
|
|
{
|
|
//
|
|
ObjName(iName);
|
|
|
|
//
|
|
// Apply Styles ...
|
|
ApplyStyle();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Private ...
|
|
private:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
int mWindowID;
|
|
long mChartID;
|
|
|
|
//
|
|
XBoxZone mRiskBox;
|
|
XBoxZone mPriceBox;
|
|
XPosition mPosition;
|
|
XBoxZone mRewardBox;
|
|
|
|
//
|
|
XCBoxObject mRiskBoxObj;
|
|
XCBoxObject mPriceBoxObj;
|
|
XCBoxObject mRewardBoxObj;
|
|
|
|
//
|
|
};
|
|
|
|
//
|
|
// Extensions ...
|
|
|
|
/**
|
|
* Add all Items of Specified CArrayObj into another ...
|
|
*
|
|
* @param source: CArrayObj, pointer refrence Specified Data Source ...
|
|
* @param dest: CArrayObj, pointer refrence Specified Destination of Adding ...
|
|
*/
|
|
void AddObjects(
|
|
CArrayObj *&source,
|
|
CArrayObj &dest //
|
|
)
|
|
{
|
|
//
|
|
bool has = source != NULL &&
|
|
source.Total() > 0;
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < source.Total(); i++)
|
|
{
|
|
dest.Add(source.At(i));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove Drawn Objects from Chart ...
|
|
*
|
|
* @param tag: Specified Object Name, if NULL remove all Objects ...
|
|
* @param chartId: long, Specified Chart ...
|
|
* @param subWindow: int Specified Sub Window ...
|
|
*/
|
|
void RemoveObjects(
|
|
string tag = NULL,
|
|
long chartId = -1,
|
|
int subWindow = -1 //
|
|
)
|
|
{
|
|
//
|
|
// Normalize Args ...
|
|
|
|
//
|
|
if (chartId == -1)
|
|
{
|
|
chartId = 0;
|
|
}
|
|
|
|
//
|
|
if (subWindow == -1)
|
|
{
|
|
subWindow = 0;
|
|
}
|
|
|
|
//
|
|
bool has = false;
|
|
string iName = NULL;
|
|
for (int iObj = ObjectsTotal(chartId, subWindow) - 1; iObj >= 0; iObj--)
|
|
{
|
|
//
|
|
// Retrieve Object Name ...
|
|
iName = ObjectName(chartId, iObj, subWindow);
|
|
|
|
//
|
|
// Check Can Delete Object or not ...
|
|
has =
|
|
!IsSpecifiedValid(tag)
|
|
? true
|
|
: StringFind(iName, tag) >= 0;
|
|
if (has)
|
|
{
|
|
ObjectDelete(chartId, iName);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Redraw Chart ...
|
|
ChartRedraw();
|
|
}
|
|
|
|
//
|
|
// Color Manipulation Functions ...
|
|
|
|
/**
|
|
* Apply Alph to Color ...
|
|
*
|
|
* @param _clr: Specified Color ...
|
|
* @param _alpha: Specified Alpha to Apply ...
|
|
*
|
|
* @return ( color )
|
|
*/
|
|
color ApplyAlpha(
|
|
color _clr,
|
|
uchar _alpha = 255 //
|
|
)
|
|
{
|
|
//
|
|
color result = _clr;
|
|
|
|
//
|
|
// Normalize ...
|
|
_alpha = (uchar)NormalizeInt(_alpha, 0, 255);
|
|
|
|
//
|
|
uchar alpha = _alpha / 255;
|
|
|
|
//
|
|
uint uintColor = ColorToARGB(_clr, alpha);
|
|
result = (color)uintColor;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
// |