Files
xMQL5/MQLTestWorkspace/BKPS/BKP/x121 old style indicators/Experts/Test/x-saherelm.xea.test.mq5
T

1354 lines
28 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Expert Advisor
// ----------------------------------------
// Name: XEA TEST
// Description: this is an expert controller
// advisors which provides a mechanism for use them ...
//
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////
//
// Global Properties ...
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://saherelm.ir"
#property version "1.00"
#property description "SaherElm XEA EA"
#property strict
//
// START Definitions ...
//
//
string mSupportToken = "SP";
string mProviderToken = "PRV";
string mRiskFreeToken = "RF";
//
enum ENUM_X_SIGNAL_PROVIDERS
{
NONE = 0,
XTRND = 1,
XICHI = 2,
XTest = 10,
};
//
// END Definitions ...
//
//
// START Inputs ...
//
//
// EA ...
input group "Common";
input bool xEAEnable = true; // Enable EA
input int xEASlippage = 10; // Slippgae
input ulong xEAMagicNumber = 1604056; // Magic Number
//
// Signals ...
input group "Signals";
input bool xEAEnableLongs = true; // Enable Long Trades
input bool xEAEnableShorts = true; // Enable Short Trades
//
// Alerts ...
input group "Alerts";
input bool xEAEnableAlerts = true; // Enable Events Alert
input bool xEAEnableHourlyAlerts = false; // Send Alert on each new Hour
input bool xEAEnableDailyAlerts = false; // Send Alert on each new Day
input bool xEAEnableWeeklyAlerts = false; // Send Alert on each new Week
input bool xEAEnableMonthlyAlerts = false; // Send Alert on each new Month
//
// END Inputs ...
//
//
// START Including Providers ...
//
//
// Classes ...
#include "../../Classes/x-saherelm.xtrade.class.mq5"
#include "../../Classes/x-saherelm.xaccount.class.mq5"
#include "../../Classes/x-saherelm.xdatacollector.class.mq5"
//
// Test Provider Library ...
#include "../../Providers/Test/x121.test.provider.mq5"
//
// END Including Providers ...
//
//
// START Global Definitions: Variables, Properties and etc ...
//
//
bool isXEANewHour;
bool isXEANewDay;
bool isXEANewWeek;
bool isXEANewMonth;
//
// Determines EA is Running On Test Mode or not ...
bool xEAIsTestMode = false;
//
// Check prevent Double Signalling on Same Candle ...
bool xEAWaitUntilNextCandle = false;
//
XSCTrade *xEATrade;
XSCAccount *xEAAccount;
XSCDataCollector *xEACollector;
//
// END Global Definitions: Variables, Properties and etc ...
//
//
// START Event Handlers ...
//
//
// Initialization ...
int OnInit()
{
//
logTag = "XEA";
drawPrefix = logTag;
alertPrefix = logTag;
//
// Reset Timings ...
ResetTiming();
//
// Validate Inputs ...
if (!ValidateInputs())
{
return INIT_PARAMETERS_INCORRECT;
}
//
// Init Provider ...
if (!XTestPRVDOnInit())
{
return INIT_FAILED;
}
//
xEAIsTestMode = IsRunningOnTestMode();
//
xEACollector = new XSCDataCollector("XTestEA");
xEACollector.CleanStore();
//
// Initialize Trade Class ...
xEATrade = new XSCTrade(
xEASlippage,
xEAMagicNumber);
//
// Attach Event Handlers ...
xEATrade.AddOnStopLossEventHandler(OnStopLossTriggered);
xEATrade.AddOnTakeProfitEventHandler(OnTakeProfitTriggered);
xEATrade.AddOnDealsChangedEventHandler(OnDealsChangedHandler);
xEATrade.AddOnOrdersChangedEventHandler(OnOrdersChangedHandler);
//
// Initialize Account Class ...
xEAAccount = new XSCAccount();
//
// Init Succeed ...
return INIT_SUCCEEDED;
}
//
// DeInitialization ...
void OnDeinit(const int reason)
{
//
// REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function
// REASON_REMOVE 1 Program removed from a chart
// REASON_RECOMPILE 2 Program recompiled
// REASON_CHARTCHANGE 3 A symbol or a chart period is changed
// REASON_CHARTCLOSE 4 Chart closed
// REASON_PARAMETERS 5 Inputs changed by a user
// REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings
// REASON_TEMPLATE 7 Another chart template applied
// REASON_INITFAILED 8 The OnInit() handler returned a non-zero value
// REASON_CLOSE 9 Terminal closed
//
// Here we can handle De Initialization Reasons ...
delete xEATrade;
delete xEAAccount;
delete xEACollector;
//
// De Initialize XEA Providers ...
XTestPRVDOnDeInit();
}
//
// On Tick Handler ...
void OnTick()
{
//
// Handle Monthly Alert ...
bool isFirstMonth = xMonth == -1;
isXEANewMonth = IsNewMonth();
bool canMonthlyAlert =
isXEANewMonth &&
xEAEnableAlerts &&
xEAEnableMonthlyAlerts;
if (canMonthlyAlert)
{
//
string message = "New Month ...";
//
SendAlert(message);
}
//
// Handle Weekly Alert ...
bool isFirstWeek = xDayOfWeek == -1;
isXEANewWeek = IsNewWeek();
bool canWeeklyAlert =
isXEANewWeek &&
xEAEnableAlerts &&
xEAEnableWeeklyAlerts;
if (canWeeklyAlert)
{
//
string message = "New Week ...";
//
SendAlert(message);
}
//
// Handle Daily Alert ...
bool isFirstDay = xDay == -1;
isXEANewDay = IsNewDay();
bool canDailyAlert =
isXEANewDay &&
xEAEnableAlerts &&
xEAEnableDailyAlerts;
if (canDailyAlert)
{
//
string message = "New Day ...";
//
SendAlert(message);
}
//
// Handle Hourly Alert ...
bool isFirstHour = xHour == -1;
isXEANewHour = IsNewHour();
bool canHourlyAlert =
isXEANewHour &&
xEAEnableAlerts &&
xEAEnableHourlyAlerts;
if (canHourlyAlert)
{
//
string message = "New Hour ...";
//
SendAlert(message);
}
//
// Prevent Going Forward if user Disable it ...
if (xEAEnable)
{
//
// Call All Providers OnTick Method ...
XTestPRVDOnTick();
//
// Do all Guard Mechanism ...
HandleGuard();
//
// Check Can Ignore Tick or not ..
bool canIgnoreTick = xEAIsTestMode
? !IsNewCandle()
: !IsNewCandle() && xEAWaitUntilNextCandle;
if (canIgnoreTick)
{
return;
}
//
xEAWaitUntilNextCandle = false;
//
XSignal signal;
bool hasSignal = XTestPRVDProcessSignals(signal);
if (hasSignal)
{
//
xEAWaitUntilNextCandle = true;
OnSignalRecieved(signal);
}
}
}
//
// Handle Trade Events ...
void OnTrade()
{
//
// Process Trades ...
xEATrade.HandleOnTrade();
}
//
// END Event Handlers ...
//
//
// START Functions ...
//
//
// Validate Input Args for Initialization ...
bool ValidateInputs()
{
//
// TODO: Fix this ...
bool result = true;
//
// Validate Args ...
result =
//
xEASlippage > 0 &&
xEAMagicNumber > 0
//
;
//
// Logging State ...
string message = "Validation of (" + logTag + ") Inputs " + (result ? "Succeeded" : "Failed") + " ...";
LogMessage(message);
//
return result;
}
//
// Handle Signal Recieved Event ...
void OnSignalRecieved(
XSignal &signal // Recieved Signal ...
)
{
//
// Ignore Disabled Signals ...
if ((signal.type == POSITION_TYPE_BUY && !xEAEnableLongs) ||
(signal.type == POSITION_TYPE_SELL && !xEAEnableShorts))
{
return;
}
//
if (StringLen(signal.symbol) == 0 || signal.period == NULL)
{
return;
}
//
xEACollector.CollectSignal(signal);
//
// Count Open Positions ...
int openPositionsCount = xEATrade.PositionsCount();
//
string mTagId = GenerateTag(signal);
//
// Check Last Signal ...
datetime barTime = iTime(
signal.symbol,
signal.period,
0);
//
// Retrieve Tradable Balance ...
double availableBalance = xEAAccount.GetEquity();
//
// Verify Available Balance ...
double balance = xEAAccount.GetBalance();
//
// Here i Must Calculate TP and SL based on R2R and riskable Factor ...
bool isLong = IsLong(signal.type);
//
// Check Order Mode ...
if (signal.mode == NULL)
{
//
// Set Market Execution as Default ...
signal.mode = X_ORDER_MODE_MARKET;
}
//
// Calculate Entry Price ...
if (signal.entry <= 0)
{
//
signal.entry = GetEntry(
signal.symbol,
signal.type);
}
//
// R2R ...
if (signal.r2r <= 0)
{
//
// Set Default Risk to Reward Ratio to 1 ...
signal.r2r = 1;
}
//
// Calculate TP and SL ...
double mPoint = GetPoints(signal.symbol);
//
// Normalize SL Price ...
if (signal.sl > 0)
{
signal.sl = NormalizePrice(signal.sl, signal.symbol);
}
//
// Retrieve Symbol Point Value ...
double pointValue = xEAAccount.GetPointValue(signal.symbol);
//
// Calculate Risk ...
double riskPrice = MathAbs(signal.entry - signal.sl);
riskPrice = NormalizePrice(riskPrice, signal.symbol);
//
double riskPoints = PriceToPoint(riskPrice);
riskPoints = NormalizeDouble(riskPoints, 0);
//
// Calculating Reward based On Ratio ...
double rewardPoints = riskPoints * signal.r2r;
double rewardPrice = PointToPrice(rewardPoints);
rewardPrice = NormalizePrice(rewardPrice, signal.symbol);
//
// Calculate TP Price ...
double tpValue = isLong
? signal.entry + rewardPrice
: signal.entry - rewardPrice;
//
// Calculate SL Price ...
double slValue = isLong
? signal.entry - riskPrice
: signal.entry + riskPrice;
//
// Balance Amount which we risks on each Provider's Trade ...
double amount = availableBalance * signal.riskAmount;
//
// Calculating Trade Volume based on risk Points and Amount ...
double volume = 0.02;
// xEAAccount.CalculateVolume(
// signal.symbol,
// amount,
// riskPoints);
volume = NormalizeVolume(volume, signal.symbol);
//
// Set Caculated TP, SL and Volume ...
signal.tp = tpValue;
signal.sl = slValue;
signal.volume = volume;
//
string comment = "";
int signalProvidersCount = ArraySize(signal.providers);
if (signalProvidersCount > 0)
{
//
string prvs = "";
for (int i = 0; i < signalProvidersCount; i++)
{
//
string p = signal.providers[i];
//
if (StringLen(prvs) > 0)
{
prvs += ",";
}
//
prvs += p;
}
//
comment = "PRV(" + prvs + ")";
}
//
// Here before Open Signal Position ...
// and after complete TP SL and Volume Calculations ...
// Recieve a List Of Supported Positions, based on retrieve Support and Resistance ares
// for Signal ...
XSignal supportSignals[];
xEATrade.GenerateSupportSignals(
supportSignals,
signal);
int supportSignalsCount = ArraySize(supportSignals);
//
bool isPositionOpen = xEATrade.ExecuteSignal(
signal,
comment);
//
if (isPositionOpen)
{
//
// Retrieve Position Ticket ...
ulong ticket = xEATrade.GetLastOpenPositionTicket();
if (ticket == 0)
{
return;
}
//
if (supportSignalsCount >= 0)
{
//
// Here we Must Place Orders ...
string comment = mSupportToken + "(" + (string)ticket + ")";
//
// CleanSupport Positions SLs ...
// for (int i = 0; i < supportSignalsCount; i++) {
// //
// XSignal iSignal = supportSignals[i];
// //
// // iSignal.sl = 0;
// }
//
// TODO: Add Expiration Date, Volume Calculation ...
// int executedSignals = xEATrade.ExecuteSignals(
// supportSignals,
// comment);
}
//
// Draw Signal ...
ReDrawSignal(ticket, signal);
//
// Alert Position ...
LogMessage("Position: " + (string)ticket + " was Open ...");
} else {
DrawSupportResistance(1, signal.supportAndResistance);
}
}
//
// Handle StopLoss Event ...
void OnStopLossTriggered(const XDeal &deal)
{
//
string msg = "SL: " + (string)deal.positionId;
LogMessage(msg);
//
xEACollector.CollectLog(msg);
//
xEACollector.CollectDeal(deal);
}
//
// Handle TakeProfit Event ...
void OnTakeProfitTriggered(const XDeal &deal)
{
//
string msg = "TP: " + (string)deal.positionId;
LogMessage(msg);
//
xEACollector.CollectLog(msg);
//
xEACollector.CollectDeal(deal);
}
//
void OnDealsChangedHandler(int count)
{
//
string msg = "Deals Changed: " + (string)count;
LogMessage(msg);
xEACollector.CollectLog(msg);
}
//
void OnOrdersChangedHandler(int count)
{
//
string msg = "Orders Changed: " + (string)count;
LogMessage(msg);
xEACollector.CollectLog(msg);
}
//
void HandleGuard()
{
//
// Handle Force Close Positions ...
// HandleForceClosing();
//
// Trailing Stops and Make Positions Risk Free ...
// HandleRiskFree();
//
// When all Positions Profit Going Positive ...
// HandlePyramidHedge();
//
// When a Position running in profit long time ...
// HandleCloseOldInProfitTrades();
}
//
// Force Close Provider's Signals on Special Conditions ...
void HandleForceClosing()
{
//
// Force Close all XTRND Short Positions ...
bool canCloseAllXTRNDShortPositions =
//
XTRNDForceCloseAllShorts()
//
;
if (canCloseAllXTRNDShortPositions)
{
//
XPosition positions[];
GetSpecificProviderPositions(
positions,
_Symbol,
_Period,
XTRND,
POSITION_TYPE_SELL);
int positionsCount = ArraySize(positions);
if (positionsCount > 0)
{
//
string comment = "Force Close XTRND Shorts ...";
//
xEATrade.ClosePositions(
positions,
comment);
//
DrawForceCloseEvent();
}
}
//
// Force Close all XTRND Long Positions ...
bool canCloseAllXTRNDLongPositions =
//
XTRNDForceCloseAllLongs()
//
;
if (canCloseAllXTRNDLongPositions)
{
//
XPosition positions[];
GetSpecificProviderPositions(
positions,
_Symbol,
_Period,
XTRND,
POSITION_TYPE_BUY);
int positionsCount = ArraySize(positions);
if (positionsCount > 0)
{
//
string comment = "Force Close XTRND Shorts ...";
//
xEATrade.ClosePositions(
positions,
comment);
//
DrawForceCloseEvent();
}
}
}
//
// Make Positions Risk Free and Trailing Stops ...
void HandleRiskFree()
{
//
double distanceFactorForRiskFree = 0.3;
//
XPosition inProfitPositions[];
xEATrade.GetInProfitPositions(inProfitPositions);
int inProfitPositionsCount = ArraySize(inProfitPositions);
if (inProfitPositionsCount <= 0)
{
return;
}
//
for (int i = 0; i < inProfitPositionsCount; i++)
{
//
XPosition iPosition = inProfitPositions[i];
//
// Only Make Positions Risk Free based On their SL or TP ...
if (iPosition.tp <= 0 && iPosition.sl <= 0)
{
continue;
}
//
bool isLong = IsLong(iPosition.type);
//
bool isRFBefore = StringFind(
iPosition.comment,
"RF") > 0;
//
double lastRFPrice = iPosition.entry;
string lastRFPriceStr = "";
if (isRFBefore) {
//
lastRFPriceStr = ExtractString(
iPosition.comment,
mRiskFreeToken + "(",
")"
);
if (StringLen(lastRFPriceStr) > 0) {
lastRFPrice = (double) lastRFPriceStr;
}
}
//
double tpDistancePrice = MathAbs(lastRFPrice - iPosition.tp);
double rfPrice = (tpDistancePrice * distanceFactorForRiskFree);
//
bool canRiskFree = MathAbs(lastRFPrice - iPosition.price) > rfPrice;
if (!canRiskFree)
{
continue;
}
//
double tp =
isLong
? iPosition.tp + rfPrice
: iPosition.tp - rfPrice;
double sl =
isLong
? iPosition.tp - rfPrice
: iPosition.sl - rfPrice;
//
string comment = iPosition.comment;
if (isRFBefore) {
//
StringReplace(
comment,
lastRFPriceStr,
""
);
}
//
comment += mRiskFreeToken + "(" + (string)iPosition.price + ")";
//
bool isModified = xEATrade.Modify(
iPosition.ticket,
sl,
tp,
comment);
if (isModified)
{
//
string msg = "Make Position (" + (string)iPosition.ticket + ") Risk Free ...";
LogMessage(msg);
}
}
}
//
// Pyramid Hedging ...
void HandlePyramidHedge()
{
//
int positionsCount = xEATrade.PositionsCount();
if (positionsCount <= 1)
{
return;
}
//
double minProfitForHedging = positionsCount * 1;
double positionsProfit = xEATrade.GetPositionsProfit();
//
if (positionsProfit < minProfitForHedging)
{
return;
}
//
string comment = "Pyramid Hedging ...";
//
xEATrade.CloseAllPositions(comment);
}
//
// Close In Profit Old Trades ...
void HandleCloseOldInProfitTrades()
{
//
int oldAge = 50;
double minProfit = 1;
bool onlySupports = false;
//
XPosition inProfitPositions[];
xEATrade.GetInProfitPositions(inProfitPositions);
int inProfitPositionsCount = ArraySize(inProfitPositions);
if (inProfitPositionsCount <= 0)
{
return;
}
//
for (int i = 0; i < inProfitPositionsCount; i++)
{
//
XPosition iPosition = inProfitPositions[i];
if (iPosition.profit < minProfit ||
(iPosition.tp > 0 &&
MathAbs(iPosition.entry - iPosition.price) < MathAbs(iPosition.entry - iPosition.tp) / 2))
{
continue;
}
//
// Check Position Age ...
int iPositionBarIndex = xEATrade.GetPositionOpenBarIndex(iPosition.ticket);
int iPositionAge = MathAbs(iPositionBarIndex - 0);
if (iPositionAge < oldAge)
{
continue;
}
//
string comment = "Close On Old In Profit Trade ...";
//
bool isPositionClosed = false;
//
if (onlySupports)
{
//
// Check Position is Support or not ...
bool isSupport = IsSupportPosition(iPosition);
if (isSupport)
{
//
// Close Position ...
isPositionClosed = xEATrade.Close(
iPosition.ticket,
comment);
}
}
else
{
//
// Close Position ...
isPositionClosed = xEATrade.Close(
iPosition.ticket,
comment);
}
//
// Alert Events ...
string msg = "Position (" + (string)iPosition.ticket + ") Closed due InProfit Old Event ...";
LogMessage(msg);
}
}
//
// Tools and Usefull Functions ...
//
//
// Convert Position to Signal ...
XSignal ToSignalInfo(
XPosition &position)
{
//
XSignal result;
//
result.tp = position.tp;
result.sl = position.sl;
result.type = position.type;
result.entry = position.entry;
result.symbol = position.symbol;
result.period = position.period;
result.volume = position.volume;
//
return result;
}
//
string ToString(ENUM_X_SIGNAL_PROVIDERS provider)
{
//
return EnumToString(provider);
}
//
ENUM_X_SIGNAL_PROVIDERS ToProvider(string provider)
{
//
ENUM_X_SIGNAL_PROVIDERS result;
//
if (ToString(XTest) == provider)
{
result = XTest;
}
else if (ToString(XTRND) == provider)
{
result = XTRND;
} else if (ToString(XICHI) == provider) {
result = XICHI;
} else
{
result = NONE;
}
//
return result;
}
//
// Extract Position Provider ...
ENUM_X_SIGNAL_PROVIDERS ExtractProviderFromComment(string comment)
{
//
ENUM_X_SIGNAL_PROVIDERS result = NONE;
//
if (StringLen(comment) <= 0)
{
return result;
}
//
string providerStr = ExtractString(
comment,
mProviderToken + "(",
")");
if (StringLen(providerStr) <= 0)
{
return result;
}
//
result = ToProvider(providerStr);
//
return result;
}
//
// Retrieve Specific Type of Providers Positions ...
void GetSpecificProviderPositions(
XPosition &result[], // Holds Result
string symbol, // Trading Symbol
ENUM_TIMEFRAMES period, // Trading Period
ENUM_X_SIGNAL_PROVIDERS provider, // Position Provider
ENUM_POSITION_TYPE type = NULL // Position Type
)
{
//
Clean(result);
//
if (StringLen(symbol) == 0 || provider == NONE)
{
return;
}
//
int positionsCount = xEATrade.PositionsCount();
if (positionsCount <= 0)
{
return;
}
//
XPosition symbolPeriodPositions[];
xEATrade.GetPositions(
symbolPeriodPositions,
symbol,
period);
int symbolPeriodPositionsCount = ArraySize(symbolPeriodPositions);
if (symbolPeriodPositionsCount <= 0)
{
return;
}
//
for (int i = 0; i < symbolPeriodPositionsCount; i++)
{
//
XPosition iPosition = symbolPeriodPositions[i];
//
ENUM_X_SIGNAL_PROVIDERS iProvider = ExtractProviderFromComment(iPosition.comment);
if (iProvider == NONE || iProvider != provider)
{
continue;
}
//
if (type == NULL)
{
//
Add(
iPosition,
result);
}
else if (type == iPosition.type)
{
//
Add(
iPosition,
result);
}
}
}
//
// Determines a Position is Support Position or not ...
bool IsSupportPosition(XPosition &position)
{
//
bool result = false;
//
if (StringLen(position.comment) <= 0)
{
return result;
}
//
int supTokenPos = StringFind(
position.comment,
mSupportToken + "(");
result = supTokenPos >= 0;
//
return result;
}
//
// END Functions ...
//
//
// Draw Signal ...
void ReDrawSignal(const ulong ticket, XSignal &signal)
{
//
// return;
//
DrawSupportResistance(1, signal.supportAndResistance);
//
bool isLong = IsLong(signal.type);
//
string prefix = (string)ticket + "_" + ToString(signal.period);
//
// Retrieve Time ...
datetime time = iTime(
signal.symbol,
signal.period,
0);
//
// Retrieve 3 Time ...
datetime time3 = iTime(
signal.symbol,
signal.period,
3);
//
color posColor = isLong
? clrSpringGreen
: clrTomato;
color tpColor = clrSpringGreen;
color slColor = clrTomato;
color entryColor = clrGold;
//
ENUM_LINE_STYLE vLineStyle = STYLE_DOT;
ENUM_LINE_STYLE tpLineStyle = STYLE_SOLID;
ENUM_LINE_STYLE slLineStyle = STYLE_SOLID;
ENUM_LINE_STYLE entryLineStyle = STYLE_SOLID;
//
int lineWidth = 2;
//
long chartID = ChartID();
//
// Vertical Line ...
string vlName = prefix + "_" + (string)time;
//
DrawVerticalLine(
chartID,
vlName,
0,
time,
posColor,
vLineStyle,
lineWidth);
//
// TP ...
double profit = (MathAbs(signal.tp - signal.entry)) * signal.volume;
string tpName = prefix + "_TP_" + (string)profit;
//
DrawTrendLine(
chartID,
tpName,
0,
time3,
signal.tp,
time,
signal.tp,
tpColor,
tpLineStyle,
lineWidth);
//
// SL ...
double lost = (MathAbs(signal.sl - signal.entry)) * signal.volume;
string slName = prefix + "_SL_" + (string)lost;
//
DrawTrendLine(
chartID,
slName,
0,
time3,
signal.sl,
time,
signal.sl,
slColor,
slLineStyle,
lineWidth);
//
// ENTRY ...
string entryName = prefix + "_ENTRY_" + (string)lost;
//
DrawTrendLine(
chartID,
entryName,
0,
time3,
signal.entry,
time,
signal.entry,
entryColor,
entryLineStyle,
lineWidth);
}
//
// Alert Force Close Event on Chart ...
void DrawForceCloseEvent()
{
//
datetime barTime = GetCandleTime(
_Symbol,
_Period,
1);
//
long chartID = ChartID();
string vlName = "XTRND Force Close: " + (string)barTime;
//
DrawVerticalLine(
chartID,
vlName,
0,
barTime,
clrDarkViolet,
STYLE_SOLID,
2);
}
//
void DrawSupportResistance(
int bar_index,
XOHCLSupRes &data,
string prefix = "",
color supportColor = clrLime,
color resistanceColor = clrRed)
{
//
// return;
//
datetime barTime = GetCandleTime(
_Symbol,
_Period,
bar_index);
//
datetime prevBarTime = GetCandleTime(
_Symbol,
_Period,
bar_index + 5);
//
long chID = ChartID();
int subWindiw = 0;
int lineWidth = 2;
//
string mPrefix = prefix + "_" + (string)barTime + "_";
//
// SUPPORTS ...
//
int supCount = ArraySize(data.sup);
if (supCount > 0)
{
//
for (int i = 0; i < supCount; i++)
{
//
double iSup = data.sup[i];
//
string supTlName = mPrefix + "SUP[" + (string)(i + 1) + "]_(" + (string)iSup + ")";
//
// Draw Support ...
DrawTrendLine(
chID,
supTlName,
subWindiw,
prevBarTime,
iSup,
barTime,
iSup,
supportColor,
STYLE_DOT,
lineWidth,
true);
}
}
//
// RESISTANCES ...
//
int resCount = ArraySize(data.res);
if (resCount > 0)
{
//
for (int i = 0; i < resCount; i++)
{
//
double iRes = data.res[i];
//
string resTlName = mPrefix + "RES[" + (string)(i + 1) + "]_(" + (string)iRes + ")";
//
// Draw Support ...
DrawTrendLine(
chID,
resTlName,
subWindiw,
prevBarTime,
iRes,
barTime,
iRes,
resistanceColor,
STYLE_DOT,
2,
true);
}
}
}