1387 lines
24 KiB
Plaintext
1387 lines
24 KiB
Plaintext
|
|
//
|
|
struct XOBFVGPivot
|
|
{
|
|
//
|
|
// Props ...
|
|
double value;
|
|
datetime at;
|
|
|
|
//
|
|
// Constructor ...
|
|
XOBFVGPivot()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
void Clean()
|
|
{
|
|
//
|
|
value = 0;
|
|
at = NULL;
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
//
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
value > 0 &&
|
|
IsValid(at);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
};
|
|
|
|
//
|
|
struct XOBFVG
|
|
{
|
|
//
|
|
// Props ...
|
|
XCFVG *fvgs[];
|
|
XCOrderBlock *ob;
|
|
|
|
//
|
|
// Constructor ...
|
|
XOBFVG()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
void Clean()
|
|
{
|
|
//
|
|
Clean(fvgs);
|
|
ZeroMemory(ob);
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
//
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = HasOB() &&
|
|
HasFVGs();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL passedBar;
|
|
bool isBodyOut;
|
|
bool isOBStarted = ob.IsStarted(
|
|
ob.GetDirection(),
|
|
passedBar,
|
|
isBodyOut //
|
|
);
|
|
|
|
//
|
|
int idx = GetOldest(fvgs);
|
|
result = IsValidIndex(idx);
|
|
if (!result)
|
|
{
|
|
//
|
|
passedBar.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isFVGStarted = fvgs[idx].IsStarted(
|
|
ob.GetDirection(),
|
|
passedBar,
|
|
isBodyOut //
|
|
);
|
|
|
|
//
|
|
result = isOBStarted &&
|
|
isFVGStarted;
|
|
|
|
//
|
|
passedBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasOB()
|
|
{
|
|
return ob != NULL &&
|
|
ob.IsValid();
|
|
}
|
|
|
|
//
|
|
bool HasFVGs()
|
|
{
|
|
return HasChild(fvgs);
|
|
}
|
|
|
|
//
|
|
int CountFVGs()
|
|
{
|
|
return ArraySize(fvgs);
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION GetDirection()
|
|
{
|
|
//
|
|
ENUM_X_DIRECTION result = X_DIRECTION_NONE;
|
|
|
|
//
|
|
bool isValid = IsValid();
|
|
if (!isValid)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ob.GetDirection();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool IsBullish()
|
|
{
|
|
return IsBullish(GetDirection());
|
|
}
|
|
|
|
//
|
|
bool IsBearish()
|
|
{
|
|
return IsBearish(GetDirection());
|
|
}
|
|
|
|
//
|
|
int GetSwings(
|
|
XOBFVGPivot &pivots[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(pivots);
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION forDir = GetDirection();
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
XOHCL passedBar;
|
|
XOBFVGPivot iPivot;
|
|
bool isPassed = false;
|
|
double appliedPrice = 0;
|
|
bool isBodyState = false;
|
|
|
|
//
|
|
// Start ...
|
|
isPassed = ob.IsStarted(
|
|
forDir,
|
|
passedBar,
|
|
isBodyState //
|
|
);
|
|
if (isPassed)
|
|
{
|
|
//
|
|
appliedPrice =
|
|
isBullish
|
|
? passedBar.low
|
|
: passedBar.high;
|
|
|
|
//
|
|
iPivot.Clean();
|
|
iPivot.value = appliedPrice;
|
|
iPivot.at = passedBar.time;
|
|
|
|
//
|
|
AddRef(
|
|
iPivot,
|
|
pivots //
|
|
);
|
|
|
|
//
|
|
iPivot.Clean();
|
|
}
|
|
|
|
//
|
|
// Activation ...
|
|
isPassed = ob.IsActivated(
|
|
forDir,
|
|
passedBar,
|
|
isBodyState //
|
|
);
|
|
if (isPassed)
|
|
{
|
|
//
|
|
appliedPrice =
|
|
isBullish
|
|
? passedBar.low
|
|
: passedBar.high;
|
|
|
|
//
|
|
iPivot.Clean();
|
|
iPivot.value = appliedPrice;
|
|
iPivot.at = passedBar.time;
|
|
|
|
//
|
|
AddRef(
|
|
iPivot,
|
|
pivots //
|
|
);
|
|
|
|
//
|
|
iPivot.Clean();
|
|
}
|
|
|
|
//
|
|
// Worked ...
|
|
isPassed = ob.IsWorked(
|
|
forDir,
|
|
passedBar,
|
|
isBodyState //
|
|
);
|
|
if (isPassed)
|
|
{
|
|
//
|
|
appliedPrice =
|
|
isBullish
|
|
? passedBar.low
|
|
: passedBar.high;
|
|
|
|
//
|
|
iPivot.Clean();
|
|
iPivot.value = appliedPrice;
|
|
iPivot.at = passedBar.time;
|
|
|
|
//
|
|
AddRef(
|
|
iPivot,
|
|
pivots //
|
|
);
|
|
|
|
//
|
|
iPivot.Clean();
|
|
}
|
|
|
|
//
|
|
passedBar.Clean();
|
|
|
|
//
|
|
result = ArraySize(pivots);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool GetMainFVG(
|
|
XCFVG *&fvg //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
fvg = NULL;
|
|
|
|
//
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int idx = GetOldest(fvgs);
|
|
result = IsValidIndex(idx);
|
|
if (!result)
|
|
{
|
|
//
|
|
ZeroMemory(fvg);
|
|
return result;
|
|
}
|
|
|
|
//
|
|
fvg = fvgs[idx];
|
|
result = fvg != NULL &&
|
|
fvg.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool IsValidZone(
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XCFVG *tmpFVGs[];
|
|
Copy(
|
|
fvgs,
|
|
tmpFVGs //
|
|
);
|
|
int count = CountFVGs();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCFVG *iFVG = tmpFVGs[i];
|
|
|
|
//
|
|
XOHCL startedBar;
|
|
bool isBodyOut = false;
|
|
result = iFVG.IsStarted(
|
|
iFVG.GetDirection(),
|
|
startedBar,
|
|
isBodyOut //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
ZeroMemory(iFVG);
|
|
startedBar.Clean();
|
|
ArrayRemove(
|
|
fvgs,
|
|
i,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
continue;
|
|
}
|
|
|
|
//
|
|
XOHCL bar;
|
|
bool isBullish = iFVG.IsBullish();
|
|
datetime fromTime = startedBar.NextAt();
|
|
|
|
//
|
|
int fromIndex = iBarShift(
|
|
iFVG.GetSymbol(),
|
|
iFVG.GetPeriod(),
|
|
fromTime //
|
|
);
|
|
result = IsValidIndex(fromIndex);
|
|
if (!result)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
ZeroMemory(iFVG);
|
|
startedBar.Clean();
|
|
ArrayRemove(
|
|
fvgs,
|
|
i,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isInited = false;
|
|
bool isValidFVG = false;
|
|
for (int j = barIndex; j < fromIndex; j++)
|
|
{
|
|
//
|
|
isInited = bar.Init(
|
|
iFVG.GetSymbol(),
|
|
iFVG.GetPeriod(),
|
|
j //
|
|
);
|
|
if (!isInited)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// bool isBarAbove =
|
|
// bar.low > iFVG.Upper();
|
|
// bool isBarBelow =
|
|
// bar.high < iFVG.Lower();
|
|
|
|
//
|
|
bool isBarAbove =
|
|
bar.GetDown() > iFVG.Upper();
|
|
bool isBarBelow =
|
|
bar.GetUp() < iFVG.Lower();
|
|
|
|
//
|
|
isValidFVG =
|
|
isBullish
|
|
? isBarAbove
|
|
: isBarBelow;
|
|
if (!isValidFVG)
|
|
{
|
|
//
|
|
bar.Clean();
|
|
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
bar.Clean();
|
|
}
|
|
|
|
//
|
|
if (!isValidFVG)
|
|
{
|
|
//
|
|
ArrayRemove(
|
|
fvgs,
|
|
i,
|
|
1 //
|
|
);
|
|
}
|
|
|
|
//
|
|
bar.Clean();
|
|
ZeroMemory(iFVG);
|
|
startedBar.Clean();
|
|
}
|
|
|
|
//
|
|
Clean(tmpFVGs);
|
|
|
|
//
|
|
result = HasFVGs();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool ToZone(XBoxZone &box)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = ToZoneBox(
|
|
box,
|
|
this //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void AddFVG(XCFVG *fvg)
|
|
{
|
|
//
|
|
int idx = -1;
|
|
bool has = false;
|
|
|
|
//
|
|
has =
|
|
HasOB() &&
|
|
fvg != NULL &&
|
|
fvg.IsValid() &&
|
|
ob.GetDirection() == fvg.GetDirection();
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
idx = FindIndex(
|
|
fvg,
|
|
fvgs //
|
|
);
|
|
has = !IsValidIndex(idx);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
fvg,
|
|
fvgs //
|
|
);
|
|
}
|
|
|
|
//
|
|
bool IsSameAs(XOBFVG &item)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = IsValid() &&
|
|
IsSame(ob, item.ob);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void UpdateTo(datetime value = NULL)
|
|
{
|
|
//
|
|
value = NormalizeTime(value);
|
|
|
|
//
|
|
int count = 0;
|
|
bool has = false;
|
|
|
|
//
|
|
has = HasOB();
|
|
if (has)
|
|
{
|
|
ob.To(value);
|
|
}
|
|
|
|
//
|
|
has = HasFVGs();
|
|
if (has)
|
|
{
|
|
//
|
|
count = CountFVGs();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
fvgs[i].To(value);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Update to Time of Specifiex Collection ...
|
|
*
|
|
* @param items: XOBFVG instance Collection ...
|
|
* @param value: datetime ...
|
|
*/
|
|
void SpecifiedUpdateTo(
|
|
XOBFVG &items[],
|
|
datetime value = NULL //
|
|
)
|
|
{
|
|
//
|
|
value = NormalizeTime(value);
|
|
|
|
//
|
|
int count = ArraySize(items);
|
|
bool has = HasChild(items);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
items[i].UpdateTo(value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Extract Box Zone's of Specified OBFVG ...
|
|
*
|
|
* @param box: XBoxZone instance, represent result ...
|
|
* @param obfvg: XOBFVG instance, specified Model ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToZoneBox(
|
|
XBoxZone &box,
|
|
XOBFVG &obfvg //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
// Check Model Validation ...
|
|
result = obfvg.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Model Main Fair Value Gap ...
|
|
XCFVG *fvg;
|
|
result = obfvg.GetMainFVG(fvg);
|
|
if (!result)
|
|
{
|
|
//
|
|
box.Clean();
|
|
ZeroMemory(fvg);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = fvg.IsBullish();
|
|
|
|
//
|
|
// Retrieve Main Fair Value Gap's Started Bar ...
|
|
XOHCL startedBar;
|
|
bool isBodyOut = false;
|
|
bool isStarted = fvg.IsStarted(
|
|
fvg.GetDirection(),
|
|
startedBar,
|
|
isBodyOut //
|
|
);
|
|
result = isStarted;
|
|
if (!result)
|
|
{
|
|
//
|
|
box.Clean();
|
|
ZeroMemory(fvg);
|
|
startedBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Converts Main Fair Value Gaps to Box ...
|
|
result = ToBox(
|
|
box,
|
|
fvg //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
box.Clean();
|
|
ZeroMemory(fvg);
|
|
startedBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Validate Start Bar ...
|
|
result =
|
|
isBullish
|
|
? startedBar.high >= fvg.Upper() &&
|
|
startedBar.low < fvg.Upper()
|
|
: startedBar.low <= fvg.Lower() &&
|
|
startedBar.high > fvg.Lower();
|
|
if (!result)
|
|
{
|
|
//
|
|
box.Clean();
|
|
ZeroMemory(fvg);
|
|
startedBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Update Box using Started Bar ...
|
|
box.lower = isBullish
|
|
? box.lower
|
|
: startedBar.low;
|
|
box.upper =
|
|
isBullish
|
|
? startedBar.high
|
|
: box.upper;
|
|
|
|
//
|
|
box.from = startedBar.NextAt();
|
|
|
|
//
|
|
// Check Box Validation ...
|
|
result = box.IsValid();
|
|
if (!result)
|
|
{
|
|
box.Clean();
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
ZeroMemory(fvg);
|
|
startedBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBox(
|
|
XBoxZone &box,
|
|
XOBFVG &item //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = ToBox(
|
|
box,
|
|
item.ob //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to XBoxZone ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
int ToBox(
|
|
XOBFVG &source[],
|
|
XBoxZone &dest[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(dest);
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XOBFVG iZone = source[i];
|
|
|
|
//
|
|
XBoxZone iBox;
|
|
bool hasBox = ToBox(
|
|
iBox,
|
|
iZone //
|
|
);
|
|
|
|
//
|
|
if (hasBox)
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
dest //
|
|
);
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
iZone.Clean();
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Oldest Index ...
|
|
*
|
|
* @param source: XOBFVG instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetOldest(
|
|
XOBFVG &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone tmpBoxes[];
|
|
int boxesCount = ToBox(
|
|
source,
|
|
tmpBoxes //
|
|
);
|
|
if (!IsValidSize(boxesCount))
|
|
{
|
|
//
|
|
Clean(tmpBoxes);
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < boxesCount; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = tmpBoxes[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.from > iBox.from;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(tmpBoxes);
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Youngest Index ...
|
|
*
|
|
* @param source: XOBFVG instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetYoungest(
|
|
XOBFVG &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone tmpBoxes[];
|
|
int boxesCount = ToBox(
|
|
source,
|
|
tmpBoxes //
|
|
);
|
|
if (!IsValidSize(boxesCount))
|
|
{
|
|
//
|
|
Clean(tmpBoxes);
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < boxesCount; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = tmpBoxes[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.from < iBox.from;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(tmpBoxes);
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Highest Index ...
|
|
*
|
|
* @param source: XOBFVG instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetHighest(
|
|
XOBFVG &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone tmpBoxes[];
|
|
int boxesCount = ToBox(
|
|
source,
|
|
tmpBoxes //
|
|
);
|
|
if (!IsValidSize(boxesCount))
|
|
{
|
|
//
|
|
Clean(tmpBoxes);
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < boxesCount; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = tmpBoxes[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.upper < iBox.upper;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(tmpBoxes);
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Lowest Index ...
|
|
*
|
|
* @param source: XOBFVG instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetLowest(
|
|
XOBFVG &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone tmpBoxes[];
|
|
int boxesCount = ToBox(
|
|
source,
|
|
tmpBoxes //
|
|
);
|
|
if (!IsValidSize(boxesCount))
|
|
{
|
|
//
|
|
Clean(tmpBoxes);
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < boxesCount; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = tmpBoxes[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.lower > iBox.lower;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(tmpBoxes);
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool AddIfNotExists(
|
|
XOBFVG &item,
|
|
XOBFVG &items[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int before = ArraySize(items);
|
|
|
|
//
|
|
int idx = FindIndex(
|
|
item,
|
|
items //
|
|
);
|
|
bool has = IsValidIndex(idx);
|
|
result = !has;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
AddRef(
|
|
item,
|
|
items //
|
|
);
|
|
|
|
//
|
|
int after = ArraySize(items);
|
|
|
|
//
|
|
result = after > before;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
int AddIfNotExists(
|
|
XOBFVG &items[],
|
|
XOBFVG &sources[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
bool has = HasChild(items);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int before = ArraySize(sources);
|
|
|
|
//
|
|
int count = ArraySize(items);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = AddIfNotExists(
|
|
items[i],
|
|
sources //
|
|
);
|
|
}
|
|
|
|
//
|
|
int after = ArraySize(sources);
|
|
|
|
//
|
|
result = after > before;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int DrawOBFVG(
|
|
//
|
|
XOBFVG &item,
|
|
XCBaseObject *&objects[],
|
|
//
|
|
bool drawOrderBlock = true,
|
|
bool drawFairValueGaps = true,
|
|
bool drawAllFVGs = true,
|
|
//
|
|
bool drawOBStartedBar = true,
|
|
bool drawOBActivatedBar = true,
|
|
bool drawOBBreakedBar = true,
|
|
bool drawOBWorkedBar = true,
|
|
//
|
|
bool drawFVGStartedBar = true,
|
|
bool drawFVGActivatedBar = true,
|
|
bool drawFVGBreakedBar = true,
|
|
bool drawFVGWorkedBar = true,
|
|
//
|
|
// Order Block Specs ...
|
|
//
|
|
int widthOBStartedBar = 1,
|
|
color clrOBStartedBar = clrYellow,
|
|
ENUM_LINE_STYLE styleOBStartedBar = STYLE_SOLID,
|
|
//
|
|
int widthOBActivatedBar = 1,
|
|
color clrOBActivatedBar = clrLime,
|
|
ENUM_LINE_STYLE styleOBActivatedBar = STYLE_SOLID,
|
|
//
|
|
int widthOBBreakedBar = 1,
|
|
color clrOBBreakedBar = clrRed,
|
|
ENUM_LINE_STYLE styleOBBreakedBar = STYLE_SOLID,
|
|
//
|
|
int widthOBWorkedBar = 1,
|
|
color clrOBWorkedBar = clrAqua,
|
|
ENUM_LINE_STYLE styleOBWorkedBar = STYLE_SOLID,
|
|
//
|
|
// Fair Value Gap Specs ...
|
|
//
|
|
int widthFVGStartedBar = 1,
|
|
color clrFVGStartedBar = clrYellow,
|
|
ENUM_LINE_STYLE styleFVGStartedBar = STYLE_SOLID,
|
|
//
|
|
int widthFVGActivatedBar = 1,
|
|
color clrFVGActivatedBar = clrLime,
|
|
ENUM_LINE_STYLE styleFVGActivatedBar = STYLE_SOLID,
|
|
//
|
|
int widthFVGBreakedBar = 1,
|
|
color clrFVGBreakedBar = clrRed,
|
|
ENUM_LINE_STYLE styleFVGBreakedBar = STYLE_SOLID,
|
|
//
|
|
int widthFVGWorkedBar = 1,
|
|
color clrFVGWorkedBar = clrAqua,
|
|
ENUM_LINE_STYLE styleFVGWorkedBar = STYLE_SOLID
|
|
//
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(objects);
|
|
|
|
//
|
|
bool isValid = item.IsValid();
|
|
if (!isValid)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = 0;
|
|
bool has = false;
|
|
bool isCreated = false;
|
|
XCBaseObject *tmpObjects[];
|
|
|
|
//
|
|
// Order Block ...
|
|
has = item.HasOB();
|
|
if (has &&
|
|
drawOrderBlock)
|
|
{
|
|
//
|
|
Clean(tmpObjects);
|
|
count = DrawOrderBlock(
|
|
item.ob,
|
|
tmpObjects,
|
|
drawOBStartedBar,
|
|
drawOBActivatedBar,
|
|
drawOBBreakedBar,
|
|
drawOBWorkedBar,
|
|
widthOBStartedBar,
|
|
clrOBStartedBar,
|
|
styleOBStartedBar,
|
|
widthOBActivatedBar,
|
|
clrOBActivatedBar,
|
|
styleOBActivatedBar,
|
|
widthOBBreakedBar,
|
|
clrOBBreakedBar,
|
|
styleOBBreakedBar,
|
|
widthOBWorkedBar,
|
|
clrOBWorkedBar,
|
|
styleOBWorkedBar //
|
|
);
|
|
has = IsValidSize(count);
|
|
if (has)
|
|
{
|
|
//
|
|
Copy(
|
|
tmpObjects,
|
|
objects,
|
|
false //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fair Value Gap ...
|
|
if (!drawAllFVGs)
|
|
{
|
|
XCFVG *fvg;
|
|
has = item.GetMainFVG(fvg);
|
|
if (has &&
|
|
drawFairValueGaps)
|
|
{
|
|
//
|
|
Clean(tmpObjects);
|
|
int fvgsCount = DrawFairValueGap(
|
|
fvg,
|
|
tmpObjects,
|
|
drawFVGStartedBar,
|
|
drawFVGActivatedBar,
|
|
drawFVGBreakedBar,
|
|
drawFVGWorkedBar,
|
|
widthFVGStartedBar,
|
|
clrFVGStartedBar,
|
|
styleFVGStartedBar,
|
|
widthFVGActivatedBar,
|
|
clrFVGActivatedBar,
|
|
styleFVGActivatedBar,
|
|
widthFVGBreakedBar,
|
|
clrFVGBreakedBar,
|
|
styleFVGBreakedBar,
|
|
widthFVGWorkedBar,
|
|
clrFVGWorkedBar,
|
|
styleFVGWorkedBar //
|
|
);
|
|
has = IsValidSize(fvgsCount);
|
|
if (has)
|
|
{
|
|
//
|
|
Copy(
|
|
tmpObjects,
|
|
objects,
|
|
false //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
has = item.HasFVGs();
|
|
if (has &&
|
|
drawFairValueGaps)
|
|
{
|
|
//
|
|
count = item.CountFVGs();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
Clean(tmpObjects);
|
|
int fvgsCount = DrawFairValueGap(
|
|
item.fvgs[i],
|
|
tmpObjects,
|
|
drawFVGStartedBar,
|
|
drawFVGActivatedBar,
|
|
drawFVGBreakedBar,
|
|
drawFVGWorkedBar,
|
|
widthFVGStartedBar,
|
|
clrFVGStartedBar,
|
|
styleFVGStartedBar,
|
|
widthFVGActivatedBar,
|
|
clrFVGActivatedBar,
|
|
styleFVGActivatedBar,
|
|
widthFVGBreakedBar,
|
|
clrFVGBreakedBar,
|
|
styleFVGBreakedBar,
|
|
widthFVGWorkedBar,
|
|
clrFVGWorkedBar,
|
|
styleFVGWorkedBar //
|
|
);
|
|
has = IsValidSize(fvgsCount);
|
|
if (has)
|
|
{
|
|
//
|
|
Copy(
|
|
tmpObjects,
|
|
objects,
|
|
false //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(tmpObjects);
|
|
|
|
//
|
|
result = ArraySize(objects);
|
|
|
|
//
|
|
return result;
|
|
}
|