Files
MQL5Data/Indicators/x-saherelm.x121.x-reply.mq5
T
saherelm cc51c0e906 last works:
- Complete XReply Bar;
- Add Region Folding Configs in Workspace Settings;
2026-08-16 15:46:50 +03:30

1388 lines
35 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Indicator
// ---------------------------------------------------
// Name: X121 XReplay
// Description: SaherElm Replay Tool ...
//
//
// 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 "2.00"
#property description "SaherElm X121 XReplay Indicator"
#property icon "../Images/SaherElm_Logo_Color.ico"
#property strict
// #region Imports ...
#include "../Libraries/x-saherelm.common.lib.mq5"
// #endregion
// #region Definitions ...
//
#define ShortName "X121 XReplay"
//
#define hideColorIDX 0
#define bullishColorIDX 1
#define bearishColorIDX 2
#define neuturalColorIDX 3
//
#define bullishState 1
#define neuturalState 0
#define bearishState -1
//
#define emptyValue 0.0
//
// an strucutre to save Chart Style ...
struct XChartStyle
{
long chartId; // chart's ID ...
ENUM_CHART_MODE mode; // chart's mode ...
bool showBidLine; // show bid line ...
bool showAskLine; // show ask line ...
bool showGrid; // show grids on chart ...
bool showVolumes; // show volumes ...
bool showTradeLevels; // Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders) ...
bool autoScroll; // chart autoscroll ...
bool quickNavigation; // chart quick navigation state ...
color foreGroundColor; // chart's foreground color ...
color backGroundColor; // chart's background color ...
color upColor; // Up Color ...
color downColor; // Down Color ...
color bullishColor; // Bullish color ...
color bearishColor; // Bearish color ...
color gridColor; // grid color ...
color bidLineColor; // bid line color ...
color askLineColor; // ask line color ...
color lineColor; // line mode and doji candlestick color ...
color stopColor; // Color of stop order levels (Stop Loss and Take Profit) ...
color volumesColor; // volumes color ...
};
// #endregion
// #region Inputs ...
input group "Replay Settings";
input int startBar = 20; // Cutof Bars
input int autoPlaySpeed = 1000; // Auto-Play Speed (ms)
input group "Presentation";
input color panelButtonTextColor = clrYellow; // Button Text Color
input color panelBackgroundColor = clrBlack; // Panel Background
input color infoColor = clrWhite; // Info Color
input color infoPanelBorderColor = clrBlack; // Info Panel Border Color
// #endregion
// #region Buffers ...
#define buffersCount 0
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_plots 1
//
// Played Bar ...
//
#define pBarOpenBufferIndex buffersCount
double pBarOpenBuffer[];
//
#define pBarHighBufferIndex buffersCount + 1
double pBarHighBuffer[];
//
#define pBarLowBufferIndex buffersCount + 2
double pBarLowBuffer[];
//
#define pBarCloseBufferIndex buffersCount + 3
double pBarCloseBuffer[];
//
#define pBarColorBufferIndex buffersCount + 4
double pBarColorBuffer[];
//
#define pBarBufferPlotIndex 0
#property indicator_label1 "XPBar Open;XPBar High;XPBar Low;XPBar Close"
#property indicator_type1 DRAW_COLOR_CANDLES
#property indicator_color1 CLR_NONE, clrDodgerBlue, clrDarkOrange
//
// Data Buffers ...
//
// #define pBarTimeBufferIndex buffersCount + 5
// datetime pBarTimeBuffer[];
//
// #define pBarTickVolumeBufferIndex buffersCount + 6
// long pBarTickVolumeBuffer[];
//
// #define pBarVolumeBufferIndex buffersCount + 7
// long pBarVolumeBuffer[];
//
// #define pBarSpreadBufferIndex buffersCount + 8
// long pBarSpreadBuffer[];
// #endregion
// #region Variables ...
//
int xReplyLimit;
int xReplyMaxLength;
int xReplyFirstBarIndex;
//
XChartStyle xReplyChartStyle;
XChartStyle xReplyClearStyle;
string xReplyChartStyleFileName = "XChartStyle_" + ShortName + "_" + _Symbol + "_" + ToXString(_Period) + ".bin";
//
// UI Object Names ...
string xReplyBtnPlay;
string xReplyBtnPrev;
string xReplyBtnNext;
string xReplyLblInfo;
string xReplyBtnPause;
string xReplyBtnReset;
//
// Replay State ...
int xReplyCandlesCount = 0;
int xReplyStartBarIndex = 0;
bool xReplyIsPlaying = false;
ulong xReplyLastPlayTick = 0;
datetime xReplyStartTime = NULL;
int xReplyCurrentVisibleBars = 0;
// #endregion
// #region Event Handlers ...
/**
* Initialize Indicator ...
*
* @return ( int )
*/
int OnInit()
{
//
bool has = false;
//
// Validate Inputs ...
has = ValidateInputs();
if (!has)
{
return INIT_PARAMETERS_INCORRECT;
}
//
// because in some cases we may have more than one input for
// calculation and we must prevent any calculation
// untill we pass the biggest input length, here we get max Input length
// and then wait until pass it ...
xReplyMaxLength = ExtractxReplyMaxLengthOfInputs();
//
// Initial Requirements ...
has = InitRequirements();
if (!has)
{
return INIT_FAILED;
}
//
// Define Index Buffers ...
DefineBuffers();
//
// Set Indicator ShortName ...
SetIndicatorName();
//
// Apply Chart Style ...
ApplyCustomChartStyle();
//
int idx = startBar;
if (idx >= Bars(_Symbol, _Period))
{
idx = Bars(_Symbol, _Period) - 10;
}
//
xReplyStartTime = iTime(_Symbol, _Period, idx);
xReplyStartBarIndex = iBarShift(_Symbol, _Period, xReplyStartTime, false);
has = xReplyStartBarIndex >= 0;
if (!has)
{
return INIT_PARAMETERS_INCORRECT;
}
//
// Create UI Panel ...
CreatePanel();
//
// Initial Draw ...
xReplyCurrentVisibleBars = 1;
DrawVisibleCandles();
UpdateInfoLabel();
//
// Enable Timer for Auto Play ...
EventSetMillisecondTimer(100);
//
// Init Succeed ...
return INIT_SUCCEEDED;
//
}
/**
* De Initialize Indicator ...
*
* @param reason: Integer, De Initialization 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
*/
void OnDeinit(const int reason)
{
//
// Show Saved Chart Style ...
ShowBars();
//
// Remove Chart Style File ...
FileDelete(xReplyChartStyleFileName);
//
// Remove UI Objects ...
RemoveUIObjects();
//
// Kill Timer ...
EventKillTimer();
}
/**
* Calculate Bars ...
*
* @param rates_total: Integer, Total Bars on Chart ...
* @param prev_calculated: Integer, Total Calculated Bars on Charts ...
* @param time: DateTime Array, History of Open Time ...
* @param open: Double Array, History of Open Prices ...
* @param high: Double Array, History of High Prices ...
* @param low: Double Array, History of Low Prices ...
* @param close: Double Array, History of Close Prices ...
* @param tick_volume: Long, History of Tick Volumes on Bar ...
* @param volume: Long, History of Trade Volumes ...
* @param spread: Double, History of Spread Price ...
*
* @return ( int )
*/
int OnCalculate(
const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[] //
)
{
//
// Prepare Buffers ...
ArraySetAsSeries(time, true);
ArraySetAsSeries(open, true);
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
ArraySetAsSeries(close, true);
ArraySetAsSeries(tick_volume, true);
ArraySetAsSeries(volume, true);
ArraySetAsSeries(spread, true);
//
// Validate Calculated Bars ...
//
bool isPassedRequiredCalculatedBars = true;
if (!isPassedRequiredCalculatedBars)
{
return prev_calculated;
}
//
xReplyLimit = (prev_calculated > rates_total || prev_calculated <= 0)
? rates_total
: (rates_total - prev_calculated) + 1;
//
// Buffers Copy ...
//
// Validate Copied Items ...
bool isPassedRequiredCopiedItems = true;
if (!isPassedRequiredCopiedItems)
{
return prev_calculated;
}
//
// Main Loop ...
for (int i = xReplyLimit - 1; i >= 0 && !IsStopped(); i--)
{
//
CalculateBuffers(
i,
prev_calculated,
rates_total,
//
open,
high,
close,
low,
tick_volume //
);
}
//
if (prev_calculated == 0)
{
//
string message = "History Finished ...";
Print(message);
}
//
return rates_total;
}
/**
* Handle Timer Event ...
*/
void OnTimer()
{
//
if (!xReplyIsPlaying)
{
return;
}
//
ulong now = GetTickCount64();
if (now - xReplyLastPlayTick >= (ulong)autoPlaySpeed)
{
//
xReplyLastPlayTick = now;
StepForward();
//
// Auto Stop at Current Market Bar ...
if (xReplyStartBarIndex - xReplyCurrentVisibleBars <= 0)
{
//
xReplyIsPlaying = false;
ObjectSetInteger(0, xReplyBtnPlay, OBJPROP_STATE, false);
ObjectSetInteger(0, xReplyBtnPause, OBJPROP_STATE, true);
}
}
}
/**
* Handle Chart Events ...
*
* @param id: int, Event id ...
* @param lparam: long, Event Long Parameter ...
* @param dparam: double, Event Double Parameter ...
* @param sparam: string, Event String Parameter ...
*/
void OnChartEvent(
const int id, // Event id ...
const long &lparam, // Event Long Parameter ...
const double &dparam, // Event Double Parameter ...
const string &sparam // Event String Parameter ...
)
{
//
// Button Clicks ...
if (id == CHARTEVENT_OBJECT_CLICK)
{
//
if (sparam == xReplyBtnNext)
{
//
StepForward();
ObjectSetInteger(0, xReplyBtnNext, OBJPROP_STATE, false);
ChartRedraw();
}
else if (sparam == xReplyBtnPrev)
{
//
StepBackward();
ObjectSetInteger(0, xReplyBtnPrev, OBJPROP_STATE, false);
ChartRedraw();
}
else if (sparam == xReplyBtnPlay)
{
//
xReplyIsPlaying = true;
ObjectSetInteger(0, xReplyBtnPlay, OBJPROP_STATE, true);
ObjectSetInteger(0, xReplyBtnPause, OBJPROP_STATE, false);
ChartRedraw();
}
else if (sparam == xReplyBtnPause)
{
//
xReplyIsPlaying = false;
ObjectSetInteger(0, xReplyBtnPause, OBJPROP_STATE, true);
ObjectSetInteger(0, xReplyBtnPlay, OBJPROP_STATE, false);
ChartRedraw();
}
else if (sparam == xReplyBtnReset)
{
//
ResetReplay();
ObjectSetInteger(0, xReplyBtnReset, OBJPROP_STATE, false);
ChartRedraw();
}
//
return;
}
//
// Keyboard Shortcuts ...
if (id == CHARTEVENT_KEYDOWN)
{
//
switch ((int)lparam)
{
//
// Arrow Right ...
case 38:
case 39:
StepForward();
break;
//
// Arrow Left ...
case 37:
case 40:
StepBackward();
break;
//
// Space ...
case 32:
xReplyIsPlaying = !xReplyIsPlaying;
ObjectSetInteger(0, xReplyBtnPlay, OBJPROP_STATE, xReplyIsPlaying);
ObjectSetInteger(0, xReplyBtnPause, OBJPROP_STATE, !xReplyIsPlaying);
ChartRedraw();
break;
//
// R ...
case 82:
ResetReplay();
break;
}
//
return;
}
}
// #endregion
// #region Custm Functions ...
/**
* Set Indicator Short Name and also we can define Buffers Labels ...
*/
void SetIndicatorName()
{
//
IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
IndicatorSetString(INDICATOR_SHORTNAME, ShortName);
}
/**
* Validate Input Args for Initialization ...
*
* @return ( bool )
*/
bool ValidateInputs()
{
//
bool result = false;
//
result =
//
startBar > 0
//
;
//
return result;
}
/**
* Extract Max Length of Inputs ...
*
* @return ( int )
*/
int ExtractxReplyMaxLengthOfInputs()
{
//
int result = 0;
//
//
return result;
}
/**
* Initial all Indicator Requirements ...
*
* @return ( false )
*
*/
bool InitRequirements()
{
//
bool result = false;
//
// Handlers ...
result = true;
//
return result;
}
/**
* Define Required Buffers ...
*/
void DefineBuffers()
{
// #region Plot Buffers ...
//
// SIGNAL Bar ...
//
// Signal Bars Color ...
ArraySetAsSeries(pBarColorBuffer, true);
SetIndexBuffer(pBarColorBufferIndex, pBarColorBuffer, INDICATOR_COLOR_INDEX);
//
// Set EMPTY_VALUE on XHK Bar Buffer ...
PlotIndexSetDouble(pBarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue);
PlotIndexSetInteger(pBarBufferPlotIndex, PLOT_SHOW_DATA, false);
//
// Open ...
ArraySetAsSeries(pBarOpenBuffer, true);
SetIndexBuffer(pBarOpenBufferIndex, pBarOpenBuffer, INDICATOR_DATA);
//
// High ...
ArraySetAsSeries(pBarHighBuffer, true);
SetIndexBuffer(pBarHighBufferIndex, pBarHighBuffer, INDICATOR_DATA);
//
// Low ...
ArraySetAsSeries(pBarLowBuffer, true);
SetIndexBuffer(pBarLowBufferIndex, pBarLowBuffer, INDICATOR_DATA);
//
// Close ...
ArraySetAsSeries(pBarCloseBuffer, true);
SetIndexBuffer(pBarCloseBufferIndex, pBarCloseBuffer, INDICATOR_DATA);
//
// Time ...
// ArraySetAsSeries(pBarTimeBuffer, true);
// SetIndexBuffer(pBarTimeBufferIndex, pBarTimeBuffer, INDICATOR_CALCULATIONS);
//
// Tick Volume ...
// ArraySetAsSeries(pBarTickVolumeBuffer, true);
// SetIndexBuffer(pBarTickVolumeBufferIndex, pBarTickVolumeBuffer, INDICATOR_CALCULATIONS);
//
// Volume ...
// ArraySetAsSeries(pBarVolumeBuffer, true);
// SetIndexBuffer(pBarVolumeBufferIndex, pBarVolumeBuffer, INDICATOR_CALCULATIONS);
//
// Spread ...
// ArraySetAsSeries(pBarSpreadBuffer, true);
// SetIndexBuffer(pBarSpreadBufferIndex, pBarSpreadBuffer, INDICATOR_CALCULATIONS);
// #endregion
}
/**
* Calculate Custom Buffers ...
*
* @param barIndex: Integer, Represent Current Bar ...
* @param prevCalculated: Integer, Represent Previous Calculated Bars ...
* @param ratesTotal: Integer, Represents All Available Bars ...
* @param open: Double Array, History of Open Prices ...
* @param high: Double Array, History of High Prices ...
* @param close: Double Array, History of Close Prices ...
* @param low: Double Array, History of Low Prices ...
* @param tickVolume: Long, History of Tick Volumes on Bar ...
*/
void CalculateBuffers(
int barIndex,
const int prevCalculated,
const int ratesTotal,
const double &open[],
const double &high[],
const double &close[],
const double &low[],
const long &tickVolume[] //
)
{
//
int barsxReplyLimit = ratesTotal;
xReplyFirstBarIndex = barsxReplyLimit - 1;
//
bool canCalculate =
barIndex <= barsxReplyLimit;
if (canCalculate)
{
//
// Calculate Values ...
CalculateValues(
barIndex,
prevCalculated,
ratesTotal,
open,
high,
close,
low,
tickVolume //
);
}
else
{
FillBuffersZero(barIndex);
}
}
/**
* Fill All Bufers to Zero Vlue for Specified Bar Index ...
*
* @param barIndex: Integer ...
*/
void FillBuffersZero(int barIndex)
{
pBarColorBuffer[barIndex] = hideColorIDX;
}
// #endregion
// #region Value Calculators ...
/**
* Calculate Values ...
*
* @param barIndex: int, Specified Bar Index ...
* @param prevCalculated: int, Provides Previous Calculated Bars ...
* @param ratesTotal: int, Provides All Availabled Bars ...
* @param open: double Collection, Provides Open Prices Time Series ...
* @param high: double Collection, Provides High Prices Time Series ...
* @param close: double Collection, Provides Close Prices Time Series ...
* @param low: double Collection, Provides Low Prices Time Series ...
* @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ...
*/
void CalculateValues(
int barIndex,
const int prevCalculated,
const int ratesTotal,
const double &open[],
const double &high[],
const double &close[],
const double &low[],
const long &tickVolume[] //
)
{
//
int lastBarIndex = barIndex + 1;
int maxBarIndex = ratesTotal;
bool isFirstBar = barIndex == xReplyFirstBarIndex;
//
// Filling Buffers ...
pBarLowBuffer[barIndex] = low[barIndex];
pBarOpenBuffer[barIndex] = open[barIndex];
pBarHighBuffer[barIndex] = high[barIndex];
pBarCloseBuffer[barIndex] = close[barIndex];
//
// Actually Bars Color Index ...
int colorIDX =
close[barIndex] >= open[barIndex]
? bullishColorIDX
: close[barIndex] < open[barIndex]
? bearishColorIDX
: neuturalColorIDX;
//
int selectedColorIDX = colorIDX;
if (barIndex <= startBar)
{
selectedColorIDX = hideColorIDX;
}
pBarColorBuffer[barIndex] = selectedColorIDX;
}
// #endregion
// #region Chart Style ...
/**
* Show Bars ...
*/
void ShowBars()
{
LoadChartStyleFromFile(xReplyChartStyle);
SetChartStyle(xReplyChartStyle);
}
/**
* Show Hide ...
*/
void HideBars()
{
SetChartStyle(xReplyClearStyle);
}
/**
* Read and Save Chart Style ...
*/
void ReadChartStyle()
{
//
if (LoadChartStyleFromFile(xReplyChartStyle))
{
return;
}
//
// Retrieve Current Chart ID ...
long chartId = ChartID();
xReplyChartStyle.chartId = chartId;
//
// Retrieve Chart Mode ...
xReplyChartStyle.mode = (ENUM_CHART_MODE)ChartGetInteger(chartId, CHART_MODE);
//
xReplyChartStyle.showBidLine = (bool)ChartGetInteger(chartId, CHART_SHOW_BID_LINE);
xReplyChartStyle.showAskLine = (bool)ChartGetInteger(chartId, CHART_SHOW_ASK_LINE);
xReplyChartStyle.showGrid = (bool)ChartGetInteger(chartId, CHART_SHOW_GRID);
xReplyChartStyle.showVolumes = (bool)ChartGetInteger(chartId, CHART_SHOW_VOLUMES);
xReplyChartStyle.showTradeLevels = (bool)ChartGetInteger(chartId, CHART_SHOW_TRADE_LEVELS);
xReplyChartStyle.autoScroll = (bool)ChartGetInteger(chartId, CHART_AUTOSCROLL);
xReplyChartStyle.quickNavigation = (bool)ChartGetInteger(chartId, CHART_QUICK_NAVIGATION);
//
xReplyChartStyle.foreGroundColor = (color)ChartGetInteger(chartId, CHART_COLOR_FOREGROUND);
xReplyChartStyle.backGroundColor = (color)ChartGetInteger(chartId, CHART_COLOR_BACKGROUND);
xReplyChartStyle.upColor = (color)ChartGetInteger(chartId, CHART_COLOR_CHART_UP);
xReplyChartStyle.downColor = (color)ChartGetInteger(chartId, CHART_COLOR_CHART_DOWN);
xReplyChartStyle.bullishColor = (color)ChartGetInteger(chartId, CHART_COLOR_CANDLE_BULL);
xReplyChartStyle.bearishColor = (color)ChartGetInteger(chartId, CHART_COLOR_CANDLE_BEAR);
xReplyChartStyle.gridColor = (color)ChartGetInteger(chartId, CHART_COLOR_GRID);
xReplyChartStyle.bidLineColor = (color)ChartGetInteger(chartId, CHART_COLOR_BID);
xReplyChartStyle.askLineColor = (color)ChartGetInteger(chartId, CHART_COLOR_ASK);
xReplyChartStyle.stopColor = (color)ChartGetInteger(chartId, CHART_COLOR_STOP_LEVEL);
xReplyChartStyle.lineColor = (color)ChartGetInteger(chartId, CHART_COLOR_CHART_LINE);
xReplyChartStyle.volumesColor = (color)ChartGetInteger(chartId, CHART_COLOR_VOLUME);
//
SaveChartStyleToFile(xReplyChartStyle);
}
/**
* Setting Chart Style based on given Configuration ...
*
* @param mChartStyle: XChartStyle instance ...
*/
void SetChartStyle(
XChartStyle &mChartStyle // Chart Style to Apply
)
{
//
ApplyChartStyle(
mChartStyle.chartId,
mChartStyle.mode,
mChartStyle.showBidLine,
mChartStyle.showAskLine,
mChartStyle.showGrid,
mChartStyle.showVolumes,
mChartStyle.showTradeLevels,
mChartStyle.autoScroll,
mChartStyle.quickNavigation,
mChartStyle.foreGroundColor,
mChartStyle.backGroundColor,
mChartStyle.upColor,
mChartStyle.downColor,
mChartStyle.bullishColor,
mChartStyle.bearishColor,
mChartStyle.gridColor,
mChartStyle.bidLineColor,
mChartStyle.askLineColor,
mChartStyle.lineColor,
mChartStyle.stopColor,
mChartStyle.volumesColor);
}
/**
* Setting Chart Style by Providing required data ...
*
* @param mChartId: int, Chart ID ...
* @param mMode: ENUM_CHART_MODE, Chart Bars Style ...
* @param mShowBidLine: bool, Show Bid Line ...
* @param mShowAskLine: bool, Show Ask Line ...
* @param mShowGrid: bool, Show Grids ...
* @param mShowVolumes: bool, Show Volumes ...
* @param mShowTradeLevels: bool, Show Trade Levels ...
* @param mAutoScroll: bool, Auto Scroll Chart ...
* @param mQuickNavigation: bool, Show Quick Navigations ...
* @param mForeGroundColor: color, Foreground Color ...
* @param mBackGroundColor: color, Background Color ...
* @param mUpColor: color, Up Bars Color ...
* @param mDownColor: color, Down Bars Color ...
* @param mBullishColor: color, Bullish Bars Color ...
* @param mBearishColor: color, Bearish Bars Color ...
* @param mGridColor: color, Chart Grid Color ...
* @param mBidLineColor: color, Bid Line Color ...
* @param mAskLineColor: color, Ask Line Color ...
* @param mLineColor: color, Bars Line Color ...
* @param mStopColor: color, Trading Stop Color ...
* @param mVolumesColor: color, Volumes Bar Color ...
*/
void ApplyChartStyle(
long mChartId = -1, // chart's ID
ENUM_CHART_MODE mMode = CHART_CANDLES, // chart's mMode
bool mShowBidLine = true, // show bid line
bool mShowAskLine = true, // show ask line
bool mShowGrid = false, // show grids on chart
bool mShowVolumes = false, // show volumes
bool mShowTradeLevels = true, // Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders)
bool mAutoScroll = true, // chart autoscroll
bool mQuickNavigation = true, // chart quick navigation state
color mForeGroundColor = clrWhite, // chart's foreground color
color mBackGroundColor = clrBlack, // chart's background color
color mUpColor = clrGreen, // Up Color
color mDownColor = clrRed, // Down Color
color mBullishColor = clrGreen, // Bullish color
color mBearishColor = clrRed, // Bearish color
color mGridColor = clrGray, // grid color
color mBidLineColor = clrGray, // bid line color
color mAskLineColor = clrRed, // ask line color
color mLineColor = clrLime, // line mMode and doji candlestick color
color mStopColor = clrGold, // Color of stop order levels (Stop Loss and Take Profit)
color mVolumesColor = clrGreen // volumes color
)
{
//
// Validate Args ...
if (mChartId == -1)
{
mChartId = 0;
}
//
ChartSetInteger(mChartId, CHART_MODE, mMode);
ChartSetInteger(mChartId, CHART_SHOW_BID_LINE, mShowBidLine);
ChartSetInteger(mChartId, CHART_SHOW_ASK_LINE, mShowAskLine);
ChartSetInteger(mChartId, CHART_SHOW_GRID, mShowGrid);
ChartSetInteger(mChartId, CHART_SHOW_VOLUMES, mShowVolumes);
ChartSetInteger(mChartId, CHART_SHOW_TRADE_LEVELS, mShowTradeLevels);
ChartSetInteger(mChartId, CHART_AUTOSCROLL, mAutoScroll);
ChartSetInteger(mChartId, CHART_QUICK_NAVIGATION, mQuickNavigation);
ChartSetInteger(mChartId, CHART_COLOR_FOREGROUND, mForeGroundColor);
ChartSetInteger(mChartId, CHART_COLOR_BACKGROUND, mBackGroundColor);
ChartSetInteger(mChartId, CHART_COLOR_CHART_UP, mUpColor);
ChartSetInteger(mChartId, CHART_COLOR_CHART_DOWN, mDownColor);
ChartSetInteger(mChartId, CHART_COLOR_CANDLE_BULL, mBullishColor);
ChartSetInteger(mChartId, CHART_COLOR_CANDLE_BEAR, mBearishColor);
ChartSetInteger(mChartId, CHART_COLOR_GRID, mGridColor);
ChartSetInteger(mChartId, CHART_COLOR_BID, mBidLineColor);
ChartSetInteger(mChartId, CHART_COLOR_ASK, mAskLineColor);
ChartSetInteger(mChartId, CHART_COLOR_STOP_LEVEL, mStopColor);
ChartSetInteger(mChartId, CHART_COLOR_CHART_LINE, mLineColor);
ChartSetInteger(mChartId, CHART_COLOR_VOLUME, mVolumesColor);
//
ChartRedraw();
}
/**
* Apply Custom Chart Style ...
*/
void ApplyCustomChartStyle()
{
//
// Read Current Chart Config and Store it ...
ReadChartStyle();
//
// After Reading Current Chart Style ...
// we have to Save Configs and Change Styles ...
xReplyClearStyle = xReplyChartStyle;
//
xReplyClearStyle.upColor = CLR_NONE;
xReplyClearStyle.downColor = CLR_NONE;
xReplyClearStyle.lineColor = CLR_NONE;
xReplyClearStyle.bullishColor = CLR_NONE;
xReplyClearStyle.bearishColor = CLR_NONE;
//
// Decide to Show or not Candles based on User Input ...
HideBars();
}
/**
* Save Chart Style ...
*
* @param style: XChartStyle instance ...
*
* @return ( bool )
*/
bool SaveChartStyleToFile(
const XChartStyle &style //
)
{
//
bool result = false;
//
// Create a File Handler for Writing Content to File ...
int fileHandler = FileOpen(xReplyChartStyleFileName, FILE_WRITE | FILE_BIN | FILE_COMMON);
result = fileHandler != INVALID_HANDLE;
if (!result)
{
return result;
}
//
// Writing Struct to File ...
uint bytesWritten = FileWriteStruct(fileHandler, style);
FileClose(fileHandler);
result = bytesWritten > 0;
//
return result;
}
/**
* Load Chart Style ...
*
* @param style: XChartStyle instance ...
*
* @return ( bool )
*/
bool LoadChartStyleFromFile(
XChartStyle &style //
)
{
//
bool result = false;
//
// Create a File Handler for Reading File Content ...
int fileHandler = FileOpen(xReplyChartStyleFileName, FILE_READ | FILE_BIN | FILE_COMMON);
result = fileHandler != INVALID_HANDLE;
if (!result)
{
return result;
}
//
// Read File Content and Fill Struct ...
uint bytesRead = FileReadStruct(fileHandler, style);
FileClose(fileHandler);
//
result = bytesRead > 0;
if (!result)
{
return result;
}
//
return result;
}
// #endregion
// #region UI ...
/**
* Create UI Panel ...
*/
void CreatePanel()
{
//
xReplyBtnPlay = ShortName + "_BTN_PLAY";
xReplyBtnPause = ShortName + "_BTN_PAUSE";
xReplyBtnPrev = ShortName + "_BTN_PREV";
xReplyBtnNext = ShortName + "_BTN_NEXT";
xReplyBtnReset = ShortName + "_BTN_RESET";
xReplyLblInfo = ShortName + "_LBL_INFO";
//
int x = 20;
int y = 30;
int w = 45;
int h = 30;
int gap = 5;
//
// Prev Button ...
CreateButton(
xReplyBtnPrev,
x,
y,
w,
h,
"|<",
clrLightSkyBlue //
);
//
// Play Button ...
CreateButton(
xReplyBtnPlay,
x + (w + gap) * 1,
y,
w,
h,
">",
clrLimeGreen //
);
//
// Pause Button ...
CreateButton(
xReplyBtnPause,
x + (w + gap) * 2,
y,
w,
h,
"||",
clrGoldenrod //
);
//
// Next Button ...
CreateButton(
xReplyBtnNext,
x + (w + gap) * 3,
y,
w,
h,
">|",
clrLightSkyBlue //
);
//
// Reset Button ...
CreateButton(
xReplyBtnReset,
x + (w + gap) * 4,
y,
w,
h,
"R",
clrTomato //
);
//
// Info Label ...
ObjectCreate(0, xReplyLblInfo, OBJ_EDIT, 0, 0, 0);
ObjectSetInteger(0, xReplyLblInfo, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, xReplyLblInfo, OBJPROP_YDISTANCE, y + h + gap);
ObjectSetInteger(0, xReplyLblInfo, OBJPROP_XSIZE, (w + gap) * 5 - gap);
ObjectSetInteger(0, xReplyLblInfo, OBJPROP_YSIZE, 22);
ObjectSetInteger(0, xReplyLblInfo, OBJPROP_BGCOLOR, panelBackgroundColor);
ObjectSetInteger(0, xReplyLblInfo, OBJPROP_COLOR, infoColor);
ObjectSetInteger(0, xReplyLblInfo, OBJPROP_BORDER_COLOR, infoPanelBorderColor);
ObjectSetInteger(0, xReplyLblInfo, OBJPROP_READONLY, true);
ObjectSetInteger(0, xReplyLblInfo, OBJPROP_FONTSIZE, 9);
ObjectSetString(0, xReplyLblInfo, OBJPROP_FONT, "Arial");
ObjectSetInteger(0, xReplyLblInfo, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, xReplyLblInfo, OBJPROP_SELECTABLE, false);
//
ChartRedraw();
}
/**
* Create Specified Button ...
*
* @param name: string, Object Name ...
* @param x: int, X Position ...
* @param y: int, Y Position ...
* @param w: int, Width ...
* @param h: int, Height ...
* @param text: int Button Text ...
* @param borderClr: color, Border Color ...
*/
void CreateButton(
string name, // Button Name ...
int x, // X Position ...
int y, // Y Position ...
int w, // Width ...
int h, // Height ...
string text, // Button Text ...
color borderClr // Border Color ...
)
{
//
ObjectCreate(0, name, OBJ_BUTTON, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
ObjectSetInteger(0, name, OBJPROP_XSIZE, w);
ObjectSetInteger(0, name, OBJPROP_YSIZE, h);
ObjectSetInteger(0, name, OBJPROP_BGCOLOR, panelBackgroundColor);
ObjectSetInteger(0, name, OBJPROP_COLOR, panelButtonTextColor);
ObjectSetInteger(0, name, OBJPROP_BORDER_COLOR, borderClr);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 11);
ObjectSetString(0, name, OBJPROP_FONT, "Arial Bold");
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, name, OBJPROP_STATE, false);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
}
/**
* Remove All Drawn Objects ...
*/
void RemoveUIObjects()
{
//
long cid = ChartID();
for (int i = ObjectsTotal(cid, 0) - 1; i >= 0; i--)
{
//
string name = ObjectName(cid, i, 0);
if (StringFind(name, ShortName + "_") >= 0)
{
ObjectDelete(cid, name);
}
}
//
ChartRedraw();
}
/**
* Update Information Label ...
*/
void UpdateInfoLabel()
{
//
int shownBars = MathMin(
xReplyCurrentVisibleBars,
xReplyStartBarIndex + 1 //
);
//
int currentBarIdx = xReplyStartBarIndex - shownBars + 1;
if (currentBarIdx < 0)
{
currentBarIdx = 0;
}
//
datetime barTime = iTime(_Symbol, _Period, currentBarIdx);
string status = xReplyIsPlaying
? "PLAYING"
: "PAUSED";
//
string info = StringFormat(
"Bar: %d / %d | %s | %s",
shownBars,
xReplyStartBarIndex + 1,
TimeToString(barTime, TIME_DATE | TIME_MINUTES),
status //
);
//
ObjectSetString(0, xReplyLblInfo, OBJPROP_TEXT, info);
ChartRedraw();
}
/**
* Handle Show Visible Bars ...
*/
void DrawVisibleCandles()
{
//
if (ArraySize(pBarColorBuffer) <= 0)
{
return;
}
//
// Destroy Existing Candle Objects ...
ArrayInitialize(pBarColorBuffer, hideColorIDX);
//
int barsToDraw = MathMin(
xReplyCurrentVisibleBars,
xReplyStartBarIndex + 1 //
);
//
int barSeconds = PeriodSeconds(_Period);
//
// Resize Candle Array ...
xReplyCandlesCount = barsToDraw;
//
// Main Loop ...
bool isBullish = false;
int colorIDX = hideColorIDX;
for (int i = 0; i < barsToDraw; i++)
{
//
int barIdx = xReplyStartBarIndex - i;
if (barIdx < 0)
{
break;
}
//
isBullish =
pBarCloseBuffer[barIdx] >= pBarOpenBuffer[barIdx];
colorIDX =
isBullish
? bullishColorIDX
: bearishColorIDX;
pBarColorBuffer[barIdx] = colorIDX;
}
//
for (int i = xReplyStartBarIndex + 1; i < ArraySize(pBarColorBuffer); i++)
{
//
isBullish =
pBarCloseBuffer[i] >= pBarOpenBuffer[i];
colorIDX =
isBullish
? bullishColorIDX
: bearishColorIDX;
pBarColorBuffer[i] = colorIDX;
}
//
ChartRedraw();
}
// #endregion
// #region Control Actions ...
/**
* Handle Step Forward Action ...
*/
void StepForward()
{
//
int maxBars = xReplyStartBarIndex + 1;
if (xReplyCurrentVisibleBars < maxBars)
{
//
xReplyCurrentVisibleBars++;
DrawVisibleCandles();
UpdateInfoLabel();
//
int currentBarIndex = xReplyStartBarIndex - xReplyCurrentVisibleBars + 1;
ScrollToBar(currentBarIndex);
}
}
/**
* Handle Step Backward Action ...
*/
void StepBackward()
{
//
if (xReplyCurrentVisibleBars > 1)
{
//
xReplyCurrentVisibleBars--;
DrawVisibleCandles();
UpdateInfoLabel();
//
int currentBarIndex = xReplyStartBarIndex - xReplyCurrentVisibleBars + 1;
ScrollToBar(currentBarIndex);
}
}
/**
* Handle Reset Reply Action ...
*/
void ResetReplay()
{
//
xReplyCurrentVisibleBars = 1;
xReplyIsPlaying = false;
//
ObjectSetInteger(0, xReplyBtnPlay, OBJPROP_STATE, false);
ObjectSetInteger(0, xReplyBtnPause, OBJPROP_STATE, true);
//
DrawVisibleCandles();
UpdateInfoLabel();
//
ScrollToBar(xReplyStartBarIndex);
}
/**
* Scroll Chart to Specified Bar Index ...
*
* @param barIndex: int, Specified Bar Index ...
*/
void ScrollToBar(int barIndex)
{
//
// Validate Bar Index ...
int totalBars = Bars(_Symbol, _Period);
if (barIndex < 0 || barIndex >= totalBars)
{
return;
}
//
// Set First Visible Bar to Specified Index ...
ChartSetInteger(ChartID(), CHART_FIRST_VISIBLE_BAR, barIndex);
ChartRedraw();
}
// #endregion