This commit is contained in:
2025-09-16 23:48:52 +03:30
parent 83ef415ca2
commit 21fe832447
5 changed files with 583 additions and 144 deletions
@@ -79,6 +79,11 @@ class XCBackTesterEA : public XCBase
double riskToRewardRatio; // Risk To Reward per Trades ...
double volume; // Default volume Per Trade ...
//
XCAlert *eaAlert; // EA Scope Alert Handler ...
XCTrade *eaTrader; // EA Scope Trade Handler ...
XCChartHelper *eaChartHelper; // Chart Helper Class ...
//
// Constructor ...
XCBackTesterEA()
@@ -656,10 +661,6 @@ class XCBackTesterEA : public XCBase
//
// Props ...
//
XCAlert *eaAlert; // EA Scope Alert Handler ...
XCTrade *eaTrader; // EA Scope Trade Handler ...
//
// Trade Event Listeners ...
TOnModify mOnModifyEventHandlers[];
@@ -672,9 +673,6 @@ class XCBackTesterEA : public XCBase
TOnPositionsChanged mPositionsChangedEventHandlers[];
TOnTradeStateChanged mTradeStateChangedEventHandlers[];
//
XCChartHelper *mChartHelper; // Chart Helper Class ...
//
// Object Props ...
@@ -729,7 +727,7 @@ class XCBackTesterEA : public XCBase
//
// Initial Chart Class Instance ...
mChartHelper = new XCChartHelper(chartId);
eaChartHelper = new XCChartHelper(chartId);
//
int startX = 5;
@@ -742,19 +740,19 @@ class XCBackTesterEA : public XCBase
//
// Buy ...
int btnBuyStartX = startX;
int btnBuySizeX = startX + defaultWidth;
int btnBuyStartY = startY;
int btnBuySizeY = startY + defaultHeight;
int btnBuyX1 = startX;
int btnBuyX2 = startX + defaultWidth;
int btnBuyY1 = startY;
int btnBuyY2 = startY + defaultHeight;
string btnBuyName = objSuffix + "BTN_BUY";
result = btnBuy.Create(
chartId,
btnBuyName,
subWindow,
btnBuyStartX,
btnBuyStartY,
btnBuySizeX,
btnBuySizeY //
btnBuyX1,
btnBuyY1,
btnBuyX2,
btnBuyY2 //
);
if (result)
{
@@ -769,19 +767,19 @@ class XCBackTesterEA : public XCBase
//
// Sell ...
int btnSellStartX = btnBuyStartX + btnBuySizeX;
int btnSellSizeX = btnSellStartX + defaultWidth;
int btnSellStartY = btnBuyStartY;
int btnSellSizeY = btnBuySizeY;
int btnSellX1 = btnBuyX1 + btnBuyX2;
int btnSellX2 = btnSellX1 + defaultWidth;
int btnSellY1 = btnBuyY1;
int btnSellY2 = btnBuyY2;
string btnSellName = objSuffix + "BTN_SELL";
result = btnSell.Create(
chartId,
btnSellName,
subWindow,
btnSellStartX,
btnSellStartY,
btnSellSizeX,
btnSellSizeY //
btnSellX1,
btnSellY1,
btnSellX2,
btnSellY2 //
);
if (result)
{
@@ -796,19 +794,19 @@ class XCBackTesterEA : public XCBase
//
// LABEL Position ID ...
int lblPositionIdStartX = btnBuyStartX;
int lblPositionIdSizeX = lblPositionIdStartX + defaultWidth;
int lblPositionIdStartY = btnSellSizeY + defaultGap;
int lblPositionIdSizeY = lblPositionIdStartY + defaultHeight;
int lblPositionIdX1 = btnBuyX1;
int lblPositionIdX2 = lblPositionIdX1 + defaultWidth;
int lblPositionIdY1 = btnSellY2 + defaultGap;
int lblPositionIdY2 = lblPositionIdY1 + defaultHeight;
string lblPositionIdName = objSuffix + "LBL_POS_ID";
result = lblPositionId.Create(
chartId,
lblPositionIdName,
subWindow,
lblPositionIdStartX,
lblPositionIdStartY,
lblPositionIdSizeX,
lblPositionIdSizeY //
lblPositionIdX1,
lblPositionIdY1,
lblPositionIdX2,
lblPositionIdY2 //
);
if (result)
{
@@ -822,19 +820,19 @@ class XCBackTesterEA : public XCBase
//
// Close ...
int btnCloseStartX = startX;
int btnCloseSizeX = btnCloseStartX + defaultWidth;
int btnCloseStartY = lblPositionIdSizeY + defaultGap;
int btnCloseSizeY = lblPositionIdSizeY + defaultHeight;
int btnCloseX1 = startX;
int btnCloseX2 = btnCloseX1 + defaultWidth;
int btnCloseY1 = lblPositionIdY2 + defaultGap;
int btnCloseY2 = btnCloseY1 + defaultHeight;
string btnCloseName = objSuffix + "BTN_CLOSE";
result = btnClose.Create(
chartId,
btnCloseName,
subWindow,
btnCloseStartX,
btnCloseStartY,
btnCloseSizeX,
btnCloseSizeY //
btnCloseX1,
btnCloseY1,
btnCloseX2,
btnCloseY2 //
);
if (result)
{
@@ -849,19 +847,19 @@ class XCBackTesterEA : public XCBase
//
// Close All ...
int btnCloseAllStartX = btnCloseSizeX + defaultGap;
int btnCloseAllSizeX = btnCloseAllStartX + defaultWidth;
int btnCloseAllStartY = lblPositionIdSizeY + defaultGap;
int btnCloseAllSizeY = lblPositionIdSizeY + defaultHeight;
int btnCloseAllX1 = btnCloseX2 + defaultGap;
int btnCloseAllX2 = btnCloseAllX1 + defaultWidth;
int btnCloseAllY1 = lblPositionIdY2 + defaultGap;
int btnCloseAllY2 = btnCloseAllY1 + defaultHeight;
string btnCloseAllName = objSuffix + "BTN_CLOSE_ALL";
result = btnCloseAll.Create(
chartId,
btnCloseAllName,
subWindow,
btnCloseAllStartX,
btnCloseAllStartY,
btnCloseAllSizeX,
btnCloseAllSizeY //
btnCloseAllX1,
btnCloseAllY1,
btnCloseAllX2,
btnCloseAllY2 //
);
if (result)
{
@@ -879,9 +877,9 @@ class XCBackTesterEA : public XCBase
//
// TP Label ...
int lblTPX1 = btnCloseStartX;
int lblTPX1 = btnCloseX1;
int lblTPX2 = lblTPX1 + defaultWidth;
int lblTPY1 = btnCloseSizeY + defaultGap;
int lblTPY1 = btnCloseY2 + defaultGap;
int lblTPY2 = lblTPY1 + defaultHeight;
string lblTPName = objSuffix + "LBL_TP";
result = lblTP.Create(
@@ -1005,9 +1003,9 @@ class XCBackTesterEA : public XCBase
//
// SL Label ...
int lblSLX1 = btnCloseAllStartX;
int lblSLX1 = btnCloseAllX1;
int lblSLX2 = lblSLX1 + defaultWidth;
int lblSLY1 = btnCloseAllSizeY + defaultGap;
int lblSLY1 = btnCloseAllY2 + defaultGap;
int lblSLY2 = lblTPY1 + defaultHeight;
string lblSLName = objSuffix + "LBL_SL";
result = lblSL.Create(
@@ -1409,8 +1407,8 @@ class XCBackTesterEA : public XCBase
void DestroyGUI()
{
//
delete mChartHelper;
ZeroMemory(mChartHelper);
delete eaChartHelper;
ZeroMemory(eaChartHelper);
//
delete btnSelectedPosInfo;
@@ -1499,8 +1497,8 @@ class XCBackTesterEA : public XCBase
//
// Reading Global Chart Info ...
int subWindow = 0;
int chartWidth = mChartHelper.Width();
ulong chartId = mChartHelper.ChartId();
int chartWidth = eaChartHelper.Width();
ulong chartId = eaChartHelper.ChartId();
//
// Read Selected Position ...
@@ -1964,7 +1962,7 @@ class XCBackTesterEA : public XCBase
//
int subWindow = 0;
ulong chartId = mChartHelper.ChartId();
ulong chartId = eaChartHelper.ChartId();
//
int btnWidth = 25;
+228 -2
View File
@@ -908,7 +908,112 @@ class XCMarketPatternDetector : public XCBase
return result;
}
bool HasTrend(
/**
* Check Specified Bar has SignalKey Bar Pattern or not ...
*
* @param bar: XOHCL, Specified Bar ...
* @param dir: ENUM_X_DIRECTION a reference for Direction ...
* @param shadowApprovedMultiplier: int, Shadow Size Approve Multiplier ...
* @param minimumPinBarRangeMultiplier: doubble, Range Size Approve Multiplier in Point ...
* @param forceDirection: bool, Apply Force Bar Type ...
*
* @return ( bool )
*/
bool IsSignalKeyBarPattern(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
int shadowApprovedMultiplier = 3,
double minimumPinBarRangeMultiplier = 4,
bool forceDirection = false //
)
{
//
bool result = false;
//
// Prepare ...
CleanDirection(dir);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Get Requirements ...
XOHCL pBar;
result = bar.GetPreviousBar(pBar);
if (!result)
{
return result;
}
//
// Chck Previous Bar must Pinned ...
result = IsPinnedBar(
pBar,
dir,
shadowApprovedMultiplier,
minimumPinBarRangeMultiplier,
forceDirection //
);
if (!result)
{
//
pBar.Clean();
return result;
}
//
// Check Direction ...
bool isBullish =
bar.IsBullish() &&
IsSpecifiedBullish(dir) &&
bar.close > pBar.high;
bool isBearish =
bar.IsBearish() &&
IsSpecifiedBearish(dir) &&
bar.close < pBar.low;
result = isBullish || isBearish;
if (!result)
{
//
pBar.Clean();
return result;
}
//
dir = bar.GetDirection();
//
result = HasDirection(dir);
//
// Cleanup Resources ...
pBar.Clean();
//
return result;
}
//
// Trending ...
/**
* Check Trend Exists Based on Swings ...
*
* @param bar: XOHCL, Specified Bar ...
* @param dir: ENUM_X_DIRECTION a reference for Direction ...
* @param swings: XOHCL Array, Holds Swings ...
* @param numberOfSwings: int, Number of Swing Points for Detect Trend ...
* @param swingShoulders: int, Swing Shoulders Approvement Length ...
*
* @return ( bool )
*/
bool HasSwingTrend(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
XOHCL &swings[],
@@ -1031,7 +1136,128 @@ class XCMarketPatternDetector : public XCBase
//
// Check Trend Based On Swings ...
//
// Check Directions ...
//
bool isBullish = false;
bool isBearish = false;
//
datetime oldestSwingLow = NULL;
datetime oldestSwingHigh = NULL;
//
// Checking Bullish Trend based on Swing Lows ...
int count = ArraySize(swingLows);
for (int i = 0; i < count - 1; i++)
{
//
has = swingLows[i].low > swingLows[i + 1].low;
isBullish =
!isBullish
? has
: isBullish && has;
if (!isBullish)
{
break;
}
//
datetime oldeTime = MathMin(swingLows[i].time, swingLows[i + 1].time);
oldestSwingLow =
!IsSpecifiedValid(oldestSwingLow)
? oldeTime
: MathMin(oldestSwingLow, oldeTime);
}
//
// Checking Bearish Trend based on Swing Highs ...
count = ArraySize(swingHighs);
for (int i = 0; i < count - 1; i++)
{
//
has = swingHighs[i].high < swingHighs[i + 1].high;
isBearish =
!isBearish
? has
: isBearish && has;
if (!isBearish)
{
break;
}
//
datetime oldeTime = MathMin(swingHighs[i].time, swingHighs[i + 1].time);
oldestSwingHigh =
!IsSpecifiedValid(oldestSwingHigh)
? oldeTime
: MathMin(oldestSwingHigh, oldeTime);
}
//
result = isBullish || isBearish;
if (!result)
{
//
iSwing.Clean();
SpecifiedClean(swingLows);
SpecifiedClean(swingHighs);
//
return result;
}
//
if (isBullish &&
isBearish &&
IsSpecifiedValid(oldestSwingLow) &&
IsSpecifiedValid(oldestSwingHigh))
{
//
// Here we Have to Detect Newest Trend or Oldest Trend ...
isBullish = oldestSwingLow < oldestSwingHigh;
isBearish = oldestSwingHigh < oldestSwingLow;
}
//
result = (isBullish && !isBearish) ||
(isBearish && !isBullish);
if (!result)
{
//
iSwing.Clean();
SpecifiedClean(swingLows);
SpecifiedClean(swingHighs);
//
return result;
}
//
if (isBullish)
{
//
Copy(
swingLows,
swings //
);
//
dir = X_DIRECTION_BULLISH;
}
else
{
//
Copy(
swingHighs,
swings //
);
//
dir = X_DIRECTION_BEARISH;
}
//
iSwing.Clean();