last works on XBackTester ...

This commit is contained in:
2025-09-14 19:19:15 +03:30
parent c2dcbf3f32
commit 76030e2cfa
5 changed files with 1738 additions and 22 deletions
+338
View File
@@ -0,0 +1,338 @@
///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Class Library
// --------------------------------------
// Name: XCChartHelper
// Description: Chart Helper Tools ...
//
// 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
//
// Imports ...
#include "../Classes/x-saherelm.base.class.mq5"
//
// Implementation ...
class XCChartHelper : public XCBase
{
//
// Public ...
public:
//
//
// Constructor ...
XCChartHelper(ulong _chartId = 0)
{
//
// Normalize Chart ID ...
mChartID = NormalizeChartId(_chartId);
}
//
// Desconstructor ...
~XCChartHelper()
{
}
//
// Actioins ...
/**
* Redraw Specified Chart ...
*/
void Redraw()
{
ChartRedraw(mChartID);
}
/**
* Chart Navigation ...
*
* @param position: ENUM_CHART_POSITION
* @param shift: int
*
* @return ( bool )
*/
bool Navigate(
const ENUM_CHART_POSITION position,
const int shift //
)
{
return (ChartNavigate(mChartID, position, shift));
}
/**
* Apply a Template to Chart ...
*
* @param filename: string file path ...
*
* @return ( bool )
*/
bool ApplyTemplate(const string filename) const
{
return (ChartApplyTemplate(mChartID, filename));
}
/**
* Take an Screenshot of Chart ...
*
* @param filename: string file path ...
* @param width: int ...
* @param height: int ...
* @param align_mode: ENUM_ALIGN_MODE ...
*
* @return ( bool )
*/
bool ScreenShot(
const string filename,
const int width,
const int height,
const ENUM_ALIGN_MODE align_mode //
) const
{
return (ChartScreenShot(mChartID, filename, width, height, align_mode));
}
/**
* Writing parameters of chart to file ...
**/
bool Save(const int file_handle)
{
//
string work_str;
int work_int;
//--- check
if (file_handle == INVALID_HANDLE || mChartID == -1)
return (false);
//--- write start marker - 0xFFFFFFFFFFFFFFFF
if (FileWriteLong(file_handle, -1) != sizeof(long))
return (false);
//--- write chart type
if (FileWriteInteger(file_handle, Type(), INT_VALUE) != INT_VALUE)
return (false);
//--- write chart symbol
work_str = Symbol();
work_int = StringLen(work_str);
if (FileWriteInteger(file_handle, work_int, INT_VALUE) != INT_VALUE)
return (false);
if (work_int != 0)
if (FileWriteString(file_handle, work_str, work_int) != work_int)
return (false);
//--- write period of chart
if (FileWriteInteger(file_handle, Period(), INT_VALUE) != sizeof(int))
return (false);
//--- write value of the "Mode" property
if (FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_MODE), INT_VALUE) != sizeof(int))
return (false);
//--- write value of the "Foreground" property
if (FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_FOREGROUND), CHAR_VALUE) != sizeof(char))
return (false);
//--- write value of the "Shift" property
if (FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHIFT), CHAR_VALUE) != sizeof(char))
return (false);
//--- write value of the "ShiftSize" property
if (FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHIFT), INT_VALUE) != sizeof(int))
return (false);
//--- write value of the "AutoScroll" property
if (FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_AUTOSCROLL), CHAR_VALUE) != sizeof(char))
return (false);
//--- write value of the "Scale" property
if (FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SCALE), INT_VALUE) != sizeof(int))
return (false);
//--- write value of the "ScaleFix" property
if (FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SCALEFIX), CHAR_VALUE) != sizeof(char))
return (false);
//--- write value of the "ScaleFix_11" property
if (FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SCALEFIX_11), CHAR_VALUE) != sizeof(char))
return (false);
//--- write value of the "FixedMax" property
if (FileWriteDouble(file_handle, ChartGetDouble(mChartID, CHART_FIXED_MAX)) != sizeof(double))
return (false);
//--- write value of the "FixedMin" property
if (FileWriteDouble(file_handle, ChartGetDouble(mChartID, CHART_FIXED_MIN)) != sizeof(double))
return (false);
//--- write the "ScalePPB" property
if (FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SCALE_PT_PER_BAR), CHAR_VALUE) != sizeof(char))
return (false);
//--- write value of the "PointsPerBar" property
if (FileWriteDouble(file_handle, ChartGetDouble(mChartID, CHART_POINTS_PER_BAR)) != sizeof(double))
return (false);
//--- write value of the "ShowOHLC" property
if (FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHOW_OHLC), CHAR_VALUE) != sizeof(char))
return (false);
//--- write value of the "ShowLineBid" property
if (FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHOW_BID_LINE), CHAR_VALUE) != sizeof(char))
return (false);
//--- write value of the "ShowLineAsk" property
if (FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHOW_ASK_LINE), CHAR_VALUE) != sizeof(char))
return (false);
//--- write value of the "ShowLastLine" property
if (FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHOW_LAST_LINE), CHAR_VALUE) != sizeof(char))
return (false);
//--- write value of the "ShowPeriodSep" property
if (FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHOW_PERIOD_SEP), CHAR_VALUE) != sizeof(char))
return (false);
//--- write value of the "ShowGrid" property
if (FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHOW_GRID), CHAR_VALUE) != sizeof(char))
return (false);
//--- write value of the "ShowVolumes" property
if (FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHOW_VOLUMES), INT_VALUE) != sizeof(int))
return (false);
//--- write value of the "ShowObjectDescr" property
if (FileWriteInteger(file_handle, (int)ChartGetInteger(mChartID, CHART_SHOW_OBJECT_DESCR), CHAR_VALUE) != sizeof(char))
return (false);
//--- successful
return (true);
}
//
// Properties ...
/**
* Get Chart ID ...
*
* @return ( ulong )
*/
ulong ChartId()
{
return mChartID;
}
/**
* Get Object Type ...
*
* @return ( int )
**/
int Type() const
{
return (0x1111);
}
/**
* Get Chart Mode ...
*
* @return ( ENUM_CHART_MODE )
**/
ENUM_CHART_MODE Mode()
{
return ((ENUM_CHART_MODE)ChartGetInteger(mChartID, CHART_MODE));
}
/**
* Get Chart Symbol ...
*
* @return ( string )
*/
string Symbol()
{
return (ChartSymbol(mChartID));
}
/**
* Get Chart Period ...
*
* @return ( ENUM_TIMEFRAMES )
*/
ENUM_TIMEFRAMES Period()
{
return (ChartPeriod(mChartID));
}
/**
* Count Chart Visible Bars ...
*
* @return ( int )
*/
int VisibleBars()
{
return ((int)ChartGetInteger(mChartID, CHART_WIDTH_IN_BARS));
}
/**
* Get Chart First Visible Bars Index ...
*
* @return ( int )
*/
int FirstVisibleBar()
{
return ((int)ChartGetInteger(mChartID, CHART_FIRST_VISIBLE_BAR));
}
/**
* Get Chart Last Visible Bars Index ...
*
* @return ( int )
*/
int LastVisibleBar()
{
//
int first = FirstVisibleBar();
int count = VisibleBars();
int result = first + count;
return result;
}
/**
* Get Chart's Specified SubWindows Minimum Price ...
*
* @param subWindow: int
* @return ( double )
*/
double PriceMin(int subWindow = 0)
{
//
// Normalize Subwindow ...
if (subWindow <= 0)
{
subWindow = 0;
}
//
return (ChartGetDouble(mChartID, CHART_PRICE_MIN, subWindow));
}
/**
* Get Chart's Specified SubWindows Maximum Price ...
*
* @param subWindow: int
* @return ( double )
*/
double PriceMax(int subWindow = 0)
{
//
// Normalize Subwindow ...
if (subWindow <= 0)
{
subWindow = 0;
}
//
return (ChartGetDouble(mChartID, CHART_PRICE_MAX, subWindow));
}
//
// Protected ...
protected:
//
// Private ...
private:
//
// Props ...
//
ulong mChartID; // Chart ID ...
};
//
+646
View File
@@ -0,0 +1,646 @@
void UpdateMainPanel()
{
//
// Validate ...
if (mChartHelper == NULL ||
mainPanel == NULL)
{
return;
}
//
bool has = false;
//
// Update Main Panel Position ...
XObjPosition mainPanelPosition;
CalculateMainPanelPosition(mainPanelPosition);
if (mainPanelPosition.IsValidForRectangle())
{
//
has = mainPanel.ShiftPoint(1, mainPanelPosition.fromTime, mainPanelPosition.fromPrice);
if (has)
{
has = mainPanel.ShiftPoint(2, mainPanelPosition.toTime, mainPanelPosition.toPrice);
}
}
}
/**
* Calculate Main Window Position ...
*
* @param position: XObjPosition
*/
void CalculateMainPanelPosition(XObjPosition &position)
{
//
position.Clean();
//
// Reading Chart Helper Requirements ...
//
string mChartSymbol = mChartHelper.Symbol();
double mPoint = GetPoints(mChartSymbol);
//
ENUM_TIMEFRAMES mChartPeriod = mChartHelper.Period();
int mChartPeriodSeconds = PeriodSeconds(mChartPeriod);
//
double mChartMinPrice = mChartHelper.PriceMin();
double mChartMaxPrice = mChartHelper.PriceMax();
int mChartVisibleBarsCount = mChartHelper.VisibleBars();
int mChartFirstBarIndex = mChartHelper.FirstVisibleBar();
//
datetime mChartFirstBarTime = GetBarTime(
mChartSymbol,
mChartPeriod,
mChartFirstBarIndex //
);
//
position.fromTime = mChartFirstBarTime + (mChartPeriodSeconds);
position.fromPrice = mChartMaxPrice - (10 * mPoint);
//
position.toTime = position.fromTime + (40 * mChartPeriodSeconds);
position.toPrice = position.fromPrice - (20 * mPoint);
//
Print(" ");
//
Print("From Time: ", position.fromTime);
Print("To Time: ", position.toTime);
//
Print(" ");
//
Print("From Price: ", position.fromPrice);
Print("To Price: ", position.toPrice);
}
///////////////////////////////////////////////////////
//
// SaherElm IT Center XTest MQL5 Expert Advisor
// -------------------------------------------------
// Name: XBackTester
// Description: a Backtest Tools Strategy Tester
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////x
//
// Global Properties ...
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://saherelm.ir"
#property version "1.00"
#property description "SaherElm XBackTester"
#property strict
//
#define ShortName "XBackTester"
//
// Imports ...
#include "../Classes/x-saherelm.x-alert.class.mq5"
#include "../Classes/x-saherelm.x-chart.helper.class.mq5"
#include "../Classes/x-saherelm.x-trade.class.mq5"
//
// Import Chart Objects ...
#include <ChartObjects/ChartObject.mqh>
#include <ChartObjects/ChartObjectsArrows.mqh>
#include <ChartObjects/ChartObjectsFibo.mqh>
#include <ChartObjects/ChartObjectsLines.mqh>
#include <ChartObjects/ChartObjectsShapes.mqh>
#include <ChartObjects/ChartObjectsTxtControls.mqh>
#include <Charts/Chart.mqh>
//
// Definitions ...
struct XObjPosition
{
//
// Props ...
datetime fromTime;
double fromPrice;
datetime toTime;
double toPrice;
//
// Constructor ...
XObjPosition()
{
Clean();
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
toPrice = 0;
fromPrice = 0;
//
toTime = NULL;
fromTime = NULL;
}
//
// Validate XWindowPosition for Rectangle ...
bool IsValidForRectangle()
{
//
bool result =
//
toPrice > 0 &&
fromPrice > 0 &&
IsSpecifiedValid(toTime) &&
IsSpecifiedValid(fromTime) &&
fromTime < toTime
//
;
//
return result;
}
};
//
// Inputs ...
//
// Common ...
input group "Common";
input long eaMagicNumber = 78692110; // Magic Number
input int eaSlippage = 10; // Slippgae
input string eaLogSuffix = ""; // Log Suffix
//
// Alert ...
// Here we Provider All Requirements for
// Configuring Alert Provider ...
input group "Alert";
input bool eAEnableAlerts = true; // Enable Alerts
input bool eALogAlerts = true; // Log Alerts
input bool eAMailAlerts = false; // Mail Alerts
input bool eAPushAlerts = false; // Push Alerts
input bool eATerminalAlerts = false; // Terminal Alerts
//
// Define Local Variables ...
//
string eaLogTag; // EA Log Prefix ...
XCAlert *eaAlert; // Alert Provider for Expert Adviser ...
XCTrade *eaTrader; // Trader of Expert Adviser ...
//
// Chart Objects and Properties ...
XCChartHelper *mChartHelper;
//
// Chart Object Class ...
//
string objSuffix;
//
// Main Panel ...
string mainPanelName;
CChartObjectRectLabel *mainPanel; // Main Panel ...
string buyButtonName;
CChartObjectButton *buyButton; // Buy Button ...
string sellButtonName;
CChartObjectButton *sellButton; // Sell Button ...
//
// Event Handlers ...
//
// Initialization ...
int OnInit()
{
//
// Validate Inputs and Required Parameters
// for EA to Works fine ...
if (!ValidateInputs())
{
return INIT_PARAMETERS_INCORRECT;
}
//
// Initialize Timer ...
if (!InitTimer())
{
return INIT_FAILED;
}
//
// Initialize all Requirements ...
if (!InitEA())
{
return INIT_FAILED;
}
//
// Initialize all GUI Objects and Classes ...
if (!InitGUI())
{
return INIT_FAILED;
}
//
// Alert Initialization ...
string msg = "Initialized Successfully ...";
eaAlert.SendAlert(msg);
//
// 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
//
// Destroy Timer ...
DestroyTimer();
//
// Destroy all GUI Requirements ...
DestroyGUI();
//
// Alert De Initialization Succeeded ...
string msg = "De Initialized Successfully ...";
eaAlert.SendAlert(msg);
//
// Destroy all EA Requirements ...
DestroyEA();
}
//
// On Tick Handler ...
void OnTick()
{
//
UpdateGUI();
}
//
// Handle On Trade Event ...
void OnTrade()
{
eaTrader.HandleOnTrade();
}
//
// On Timer ...
void OnTimer()
{
//
// TODO: Implement Time Based Functionalities ...
}
//
// Chart Event Handler ...
void OnChartEvent(
const int id,
const long &lparam,
const double &dparam,
const string &sparam //
)
{
//
// Apply Chart Event on Main Window ...
if (id == CHARTEVENT_OBJECT_CLICK)
{
//
if (mainPanel != NULL && sparam == mainPanelName)
{
//
Print("Main Panel Clicked ...");
}
}
}
//
// Custom Functions ...
/**
* Validate all Inputs of Expert Adviser ...
*
* @return ( bool )
*/
bool ValidateInputs()
{
//
bool result = false;
//
string errMessage = "";
//
bool isCommonValid = (
//
eaSlippage > 0 &&
eaMagicNumber > 0
//
);
if (!isCommonValid)
{
//
errMessage += "common configurations error;" + "\n";
}
//
result =
//
// Common ...
isCommonValid &&
//
// Otere ...
true
//
;
//
if (!result)
{
//
// Since here Logger not Initiallized, we Use Raw Print Command ...
Print(ShortName + " Errors: \n", errMessage);
}
//
return result;
}
/**
* Initialize Timer ...
*
* @return ( bool )
*/
bool InitTimer()
{
//
bool result = false;
//
// TODO: Initialize Timer if necessary ...
// result = EventSetTimer(1);
// result = EventSetMillisecondTimer(100);
result = true;
//
return result;
}
/**
* Destroy Timer ...
*/
void DestroyTimer()
{
//
// TODO: Use This ...
// EventKillTimer();
}
/**
* Initialize all Requirements for Working Fine ...
*
* @return ( bool )
*/
bool InitEA()
{
//
bool result = false;
//
// Locally Apply Changes on Prefix ...
eaLogTag = ShortName + ">" + eaLogSuffix;
//
// Create Instance of Alert Class and Configure it ...
eaAlert = new XCAlert();
eaAlert.SetPrefix(eaLogTag);
eaAlert.SetLogAlerts(eALogAlerts);
eaAlert.SetMailAlerts(eAMailAlerts);
eaAlert.SetPushAlerts(eAPushAlerts);
eaAlert.SetEnableAlerts(eAEnableAlerts);
eaAlert.SetTerminalAlerts(eATerminalAlerts);
//
// Create Trader Instance and Configure it ...
eaTrader = new XCTrade(
eaSlippage,
eaMagicNumber //
);
//
// TODO: Fix This ...
result = true;
//
return result;
}
/**
* Destroy all Initialized EA Requirements ...
*/
void DestroyEA()
{
//
delete eaAlert;
}
//
// GUI Events ...
/**
* Initialize all GUI Requirements for EA ...
*
* @return ( bool )
*/
bool InitGUI()
{
//
bool result = false;
//
int subWindow = 0;
ulong chartId = ChartID();
objSuffix = ShortName + "_";
//
// Initial Chart Class Instance ...
mChartHelper = new XCChartHelper(chartId);
//
// Create Main Panel ...
result = CreateMainPanel();
//
//
return result;
}
/**
* Update GUI based on Each Ticks ...
*/
void UpdateGUI()
{
//
// UpdateMainPanel();
}
/**
* Destroy all Initialized GUi Requirements ...
*/
void DestroyGUI()
{
//
delete mChartHelper;
ZeroMemory(mChartHelper);
//
delete mainPanel;
ZeroMemory(mainPanel);
}
//
// Custom Helper Functions ...
bool CreateMainPanel()
{
//
bool result = false;
//
if (mChartHelper == NULL)
{
return result;
}
//
int subWindow = 0;
//
mainPanelName = objSuffix + "Main_Panel";
mainPanel = new CChartObjectRectLabel();
result = mainPanel.Create(
mChartHelper.ChartId(),
mainPanelName,
subWindow,
10,
25,
400,
200 //
);
if (!result)
{
return result;
}
//
// Styling Main Panel ...
mainPanel.BackColor(clrDarkGray);
mainPanel.Tooltip(mainPanelName);
//
// Create Buttons ...
buyButtonName = objSuffix + "BTN_BUY";
buyButton = new CChartObjectButton();
result = buyButton.Create(
mChartHelper.ChartId(),
buyButtonName,
subWindow,
10,
25,
200,
100 //
);
if (!result)
{
return result;
}
//
// Apply Style of Buy Button ...
if (result)
{
}
//
return result;
}
//////////////////////////////////////////////////
//
// class XCEdit : public CEdit {
// //
// public:
// //
// string mValue;
// //
// bool OnSetText() {
// //
// Print("Object Edit End ...");
// return true;
// }
// };
// CEdit edtPositionId;
// //
// // EDIT Position ID ...
// int edtPositionIdStartX = btnSellStartX;
// int edtPositionIdSizeX = edtPositionIdStartX + 100;
// int edtPositionIdStartY = btnSellSizeY + 5;
// int edtPositionIdSizeY = edtPositionIdStartY + 50;
// string edtPositionIdName = objSuffix + "EDT_POS_ID";
// result = edtPositionId.Create(
// chartId,
// edtPositionIdName,
// subWindow,
// edtPositionIdStartX,
// edtPositionIdStartY,
// edtPositionIdSizeX,
// edtPositionIdSizeY //
// );
// if (result)
// {
// //
// // Apply Edit Position ID Style ...
// edtPositionId.Text(ToXString(selectedPositionID));
// edtPositionId.TextAlign(ALIGN_LEFT);
// }
+733 -20
View File
@@ -24,9 +24,26 @@
//
// Imports ...
#include "../Classes/x-saherelm.x-alert.class.mq5"
#include "../Classes/x-saherelm.x-rm.panel.class.mq5"
#include "../Classes/x-saherelm.x-chart.helper.class.mq5"
#include "../Classes/x-saherelm.x-trade.class.mq5"
//
// Import Chart Objects ...
#include <Arrays/ArrayObj.mqh>
#include <ChartObjects/ChartObject.mqh>
#include <ChartObjects/ChartObjectsArrows.mqh>
#include <ChartObjects/ChartObjectsFibo.mqh>
#include <ChartObjects/ChartObjectsLines.mqh>
#include <ChartObjects/ChartObjectsShapes.mqh>
#include <ChartObjects/ChartObjectsTxtControls.mqh>
#include <Charts/Chart.mqh>
#include <Controls/Button.mqh>
#include <Controls/Edit.mqh>
#include <Controls/Label.mqh>
//
// Definitions ...
//
// Inputs ...
@@ -54,7 +71,32 @@ input bool eATerminalAlerts = false; // Terminal Alerts
string eaLogTag; // EA Log Prefix ...
XCAlert *eaAlert; // Alert Provider for Expert Adviser ...
XCTrade *eaTrader; // Trader of Expert Adviser ...
XCRMPanel eaMainWindow; // Main Window ...
XCChartHelper *mChartHelper; // Chart Helper Class ...
//
// Object Props ...
//
string objSuffix;
//
CButton btnBuy;
CButton btnSell;
CButton btnClose;
CButton btnCloseAll;
CButton btnSelectedPosInfo;
//
CEdit lblPositionId;
int lblPositionIdSizeX = 0;
int lblPositionIdSizeY = 0;
int lblPositionIdStartX = 0;
int lblPositionIdStartY = 0;
ulong selectedPositionID = 0;
//
// Position Arrays ...
CArrayObj posArray;
//
// Event Handlers ...
@@ -148,6 +190,7 @@ void OnTick()
// Handle On Trade Event ...
void OnTrade()
{
//
eaTrader.HandleOnTrade();
}
@@ -168,9 +211,6 @@ void OnChartEvent(
const string &sparam //
)
{
//
// Apply Chart Event on Main Window ...
eaMainWindow.ChartEvent(id, lparam, dparam, sparam);
}
//
@@ -285,7 +325,19 @@ bool InitEA()
eaSlippage,
eaMagicNumber //
);
//
// Attach Event Handlers ...
eaTrader.AddOnDealsChangedEventHandler(OnDealsChanged);
eaTrader.AddOnStopLossEventHandler(OnStopLossTriggered);
eaTrader.AddOnOrdersChangedEventHandler(OnOrdersChanged);
eaTrader.AddOnTakeProfitEventHandler(OnTakeProfitTriggered);
eaTrader.AddOnModifyPositionEventHandler(OnPositionModified);
eaTrader.AddOnPositionsChangedEventHandler(OnPositionsChanged);
eaTrader.AddOnTradeStateChangedEventHandler(OnTradeStateChanged);
eaTrader.AddOnForceClosePositionEventHandler(OnPositionForceClosed);
eaTrader.AddOnPartialClosePositionEventHandler(OnPositionPartialClosed);
//
// TODO: Fix This ...
result = true;
@@ -317,24 +369,155 @@ bool InitGUI()
bool result = false;
//
// Initialize Application Main Window ...
result = eaMainWindow.Create(
ChartID(),
ShortName, // Dialog Name ...
0, // SubWindow ...
10, // X1 ...
35, // Y1 ...
300, // X2 ...
200 // Y2 ...
);
int subWindow = 0;
ulong chartId = ChartID();
objSuffix = ShortName + "_";
//
// Try To Run Main Window ...
// Initial Chart Class Instance ...
mChartHelper = new XCChartHelper(chartId);
//
int startX = 5;
int startY = 25;
//
// Buy ...
int btnBuyStartX = startX;
int btnBuySizeX = startX + 100;
int btnBuyStartY = startY;
int btnBuySizeY = startY + 50;
string btnBuyName = objSuffix + "BTN_BUY";
result = btnBuy.Create(
chartId,
btnBuyName,
subWindow,
btnBuyStartX,
btnBuyStartY,
btnBuySizeX,
btnBuySizeY //
);
if (result)
{
eaMainWindow.Run();
//
// Apply Buy Button Style ...
//
btnBuy.Text("Buy");
btnBuy.Color(clrYellow);
btnBuy.ColorBackground(clrGreen);
}
//
// Sell ...
int btnSellStartX = btnBuyStartX + btnBuySizeX;
int btnSellSizeX = btnSellStartX + 100;
int btnSellStartY = btnBuyStartY;
int btnSellSizeY = btnBuySizeY;
string btnSellName = objSuffix + "BTN_SELL";
result = btnSell.Create(
chartId,
btnSellName,
subWindow,
btnSellStartX,
btnSellStartY,
btnSellSizeX,
btnSellSizeY //
);
if (result)
{
//
// Apply Sell Button Style ...
//
btnSell.Text("Sell");
btnSell.Color(clrYellow);
btnSell.ColorBackground(clrDarkRed);
}
//
// LABEL Position ID ...
lblPositionIdStartX = btnBuyStartX;
lblPositionIdSizeX = lblPositionIdStartX + 100;
lblPositionIdStartY = btnSellSizeY + 5;
lblPositionIdSizeY = lblPositionIdStartY + 50;
string lblPositionIdName = objSuffix + "LBL_POS_ID";
result = lblPositionId.Create(
chartId,
lblPositionIdName,
subWindow,
lblPositionIdStartX,
lblPositionIdStartY,
lblPositionIdSizeX,
lblPositionIdSizeY //
);
if (result)
{
//
// Apply Label Position ID Style ...
lblPositionId.ReadOnly(true);
lblPositionId.Text("Pos ID: ");
lblPositionId.Color(clrYellow);
lblPositionId.ColorBackground(clrDarkGray);
}
//
// Close ...
int btnCloseStartX = startX;
int btnCloseSizeX = btnCloseStartX + 100;
int btnCloseStartY = lblPositionIdSizeY + 5;
int btnCloseSizeY = lblPositionIdSizeY + 50;
string btnCloseName = objSuffix + "BTN_CLOSE";
result = btnClose.Create(
chartId,
btnCloseName,
subWindow,
btnCloseStartX,
btnCloseStartY,
btnCloseSizeX,
btnCloseSizeY //
);
if (result)
{
//
// Apply Close Button Style ...
//
btnClose.Text("Close");
btnClose.Color(clrYellow);
btnClose.ColorBackground(clrDarkOrange);
}
//
// Close All ...
int btnCloseAllStartX = btnCloseSizeX + 5;
int btnCloseAllSizeX = btnCloseAllStartX + 100;
int btnCloseAllStartY = lblPositionIdSizeY + 5;
int btnCloseAllSizeY = lblPositionIdSizeY + 50;
string btnCloseAllName = objSuffix + "BTN_CLOSE_ALL";
result = btnCloseAll.Create(
chartId,
btnCloseAllName,
subWindow,
btnCloseAllStartX,
btnCloseAllStartY,
btnCloseAllSizeX,
btnCloseAllSizeY //
);
if (result)
{
//
// Apply Close Button Style ...
//
btnCloseAll.Text("Close All");
btnCloseAll.Color(clrYellow);
btnCloseAll.ColorBackground(clrDarkRed);
}
//
UpdateGUIState();
//
return result;
}
@@ -345,7 +528,94 @@ bool InitGUI()
void UpdateGUI()
{
//
eaMainWindow.UpdateState();
UpdateGUIState();
//
// Buy Button Pressed ...
if (btnBuy.Pressed())
{
//
HandleBuyTrade();
btnBuy.Pressed(false);
}
//
// Sell Button Pressed ...
if (btnSell.Pressed())
{
//
HandleSellTrade();
btnSell.Pressed(false);
}
//
// Close Button Pressed ...
if (btnClose.Pressed())
{
//
if (btnClose.IsEnabled())
{
//
if (selectedPositionID > 0)
{
HandleCloseTrade(selectedPositionID);
}
}
//
btnClose.Pressed(false);
}
//
// Close All Button Pressed ...
if (btnCloseAll.Pressed())
{
//
if (btnCloseAll.IsEnabled())
{
HandleCloseTrade(0);
}
//
btnCloseAll.Pressed(false);
}
//
// Check Positions Buttons ...
int posCount = posArray.Total();
bool has = IsValidSize(posCount);
if (has)
{
//
for (int i = 0; i < posCount; i++)
{
//
CButton *iBtn = (CButton *)posArray.At(i);
//
if (iBtn.Pressed())
{
//
if (iBtn.IsEnabled())
{
//
ulong posID = ExtractPositionIDFromButtonName(iBtn.Name());
if (posID > 0 && selectedPositionID != posID)
{
selectedPositionID = posID;
UpdateGUIState();
Print("Changed Selected Pos ID: ", selectedPositionID);
}
}
//
iBtn.Pressed(false);
}
//
ZeroMemory(iBtn);
}
}
}
/**
@@ -354,5 +624,448 @@ void UpdateGUI()
void DestroyGUI()
{
//
eaMainWindow.Destroy();
delete mChartHelper;
ZeroMemory(mChartHelper);
//
}
//
// Trade Event Handlers ...
/**
* Handle StopLoss Triggered Positions ...
*
* @param deal: XDeal instance ...
*/
void OnStopLossTriggered(const XDeal &deal)
{
}
/**
* Handle Take Profit Triggered Positions ...
*
* @param deal: XDeal instance ...
*/
void OnTakeProfitTriggered(const XDeal &deal)
{
}
/**
* Handle Force Close a Position ...
*
* @param ticket: ULONG ...
* @param position: XPosition instance ...
* @param comment: String ...
*/
void OnPositionForceClosed(
const ulong ticket,
const XPosition &position,
const string comment //
)
{
}
/**
* Handle Deals Changes ...
*
* @param count: Integer, Number of Changes ...
*/
void OnDealsChanged(int count)
{
}
/**
* Handle Orders Changes ...
*
* @param count: Integer, Number of Changes ...
*/
void OnOrdersChanged(int count)
{
}
/**
* Handle Positions Changes ...
*
* @param count: Integer, Number of Changes ...
*/
void OnPositionsChanged(int count)
{
//
// Update Position Buttons ...
UpdatePositionButtons();
}
/**
* Handle Position Modified ...
*
* @param ticket: ulong, Position Ticket ...
* @param profit: double, Position Profit ...
* @param comment: string, Comment ...
*/
void OnPositionModified(
const ulong ticket,
const double profit,
const string comment //
)
{
}
/**
* Handle Position Partial Closed ...
*
* @param ticket: ulong, Position Ticket ...
* @param profit: double, Position Profit ...
* @param comment: string, Comment ...
*/
void OnPositionPartialClosed(
const ulong ticket,
const double profit,
const string comment //
)
{
}
/**
* Handle Trade State Changed ...
*
* @param state: XOnTradeHandlerState instance ...
*/
void OnTradeStateChanged(const XOnTradeHandlerState &state)
{
}
//
// GUI Event Handlers and Helpers ...
//
void HandleBuyTrade()
{
HandleTrade(X_DIRECTION_BULLISH);
}
//
void HandleSellTrade()
{
HandleTrade(X_DIRECTION_BEARISH);
}
//
void HandleTrade(ENUM_X_DIRECTION dir)
{
//
if (!HasDirection(dir))
{
return;
}
//
string symbol = mChartHelper.Symbol();
ENUM_TIMEFRAMES period = mChartHelper.Period();
//
bool isBullish = IsSpecifiedBullish(dir);
//
double r2r = 1.5;
double volume = 0.01;
double riskInPoints = 100;
double point = GetPoints(symbol);
double entry = GetEntry(symbol, dir);
//
double risk = riskInPoints * point;
double reward = risk * r2r;
//
double sl = isBullish
? entry - risk
: entry + risk;
double tp = isBullish
? entry + reward
: entry - reward;
//
string comment = ShortName + "_POS_" + ToXString(dir);
//
if (isBullish)
{
//
eaTrader.Buy(
symbol,
period,
volume,
entry,
sl,
tp,
comment //
);
}
else
{
//
eaTrader.Sell(
symbol,
period,
volume,
entry,
sl,
tp,
comment //
);
}
}
//
void HandleCloseTrade(ulong positionID)
{
//
if (positionID == 0)
{
//
// Force Close All ...
Print("Close All Positions ...");
}
else
{
//
// Close Specified Position ...
Print("Close Position: ", positionID);
}
}
//
ulong ExtractPositionIDFromButtonName(string name)
{
//
ulong result = 0;
//
string nameParts[];
int namePartsCount = SplitContent(nameParts, name, "_");
bool has = IsValidSize(namePartsCount);
if (has)
{
//
string lastPart = nameParts[namePartsCount - 1];
StringReplace(lastPart, "_", "");
result = (long)lastPart;
}
//
SpecifiedClean(nameParts);
//
return result;
}
//
void UpdatePositionButtons()
{
//
// Retrieve Positions ...
XPosition positions[];
int count = eaTrader.GetPositions(
positions //
);
bool has = IsValidSize(count);
if (!has)
{
//
posArray.Clear();
selectedPositionID = 0;
return;
}
//
posArray.Clear();
//
// Selected Position ID ...
if (selectedPositionID == 0)
{
//
XPosition youngest;
int youngestIDX = GetXYoungest(youngest, positions);
bool hasYoungest = IsValidIndex(youngestIDX) &&
youngest.IsValid();
if (hasYoungest)
{
selectedPositionID = youngest.ticket;
}
//
youngest.Clean();
}
//
int subWindow = 0;
ulong chartId = mChartHelper.ChartId();
//
int btnWidth = 25;
//
int lastX = lblPositionIdSizeX + 5;
int lastSizeX = lastX + btnWidth;
//
int lastY = lblPositionIdStartY;
int lastSizeY = lblPositionIdSizeY;
//
for (int i = 0; i < count; i++)
{
//
XPosition iPos = positions[i];
//
string posTypeStr = IsLong(iPos.type)
? "LONG"
: "SHORT";
//
int iPosBtnX = lastX;
int iPosBtnSizeX = iPosBtnX + btnWidth;
string iPosBtnName = objSuffix + "_" + posTypeStr + "_POS_SELECT_BTN_" + ToXString(iPos.ticket);
//
CButton *iPosBtn = new CButton();
has = iPosBtn.Create(
chartId,
iPosBtnName,
subWindow,
iPosBtnX,
lastY,
iPosBtnSizeX,
lastSizeY //
);
if (has)
{
//
// Apply Styles ...
string iPosBtnText = ToXString(iPos.ticket);
//
iPosBtn.Text(iPosBtnText);
iPosBtn.Color(clrWhite);
//
color iPosBtnBG = IsLong(iPos.type)
? clrGreen
: clrDarkRed;
iPosBtn.ColorBackground(iPosBtnBG);
//
lastX = iPosBtnSizeX + 5;
//
if (selectedPositionID == iPos.ticket)
{
iPosBtn.Disable();
}
//
posArray.Add(iPosBtn);
}
//
iPos.Clean();
}
//
SpecifiedClean(positions);
UpdateGUIState();
}
//
void UpdateGUIState()
{
//
// Update States Of Position Select Buttons ...
int count = posArray.Total();
bool has = IsValidSize(count) && selectedPositionID > 0;
if (has)
{
//
for (int i = 0; i < count; i++)
{
//
CButton *iBtn = (CButton *)posArray.At(i);
//
ulong posID = ExtractPositionIDFromButtonName(iBtn.Name());
//
// Select Position ...
XPosition iPos;
bool hasPosition = eaTrader.GetPosition(
posID,
iPos //
);
string iTooltip =
!hasPosition
? ""
: IsLong(iPos.type)
? "Long"
: "Short";
//
if (posID == selectedPositionID)
{
//
iBtn.Disable();
iBtn.ColorBackground(clrDarkGray);
}
else
{
//
iBtn.Enable();
//
color iBtnBG = IsLong(iPos.type)
? clrGreen
: clrDarkRed;
//
iBtn.ColorBackground(iBtnBG);
}
//
ZeroMemory(iBtn);
}
}
//
// Update State of Close All ...
if (has && count > 1)
{
//
btnCloseAll.Enable();
btnCloseAll.ColorBackground(clrDarkRed);
}
else
{
//
btnCloseAll.Disable();
btnCloseAll.ColorBackground(clrDarkGray);
}
//
// Update State of BtnClose and BtnClose All ...
if (selectedPositionID == 0)
{
//
btnClose.Disable();
btnClose.ColorBackground(clrDarkGray);
}
else
{
//
btnClose.Enable();
btnClose.ColorBackground(clrDarkOrange);
}
}
//
@@ -570,6 +570,25 @@ double NormalizePrice(
return result;
}
/**
* Normalize Chart Id ...
*
* @param _chartId: ulong
*
* @return ( ulong )
*/
ulong NormalizeChartId(ulong _chartId = 0)
{
//
if (_chartId <= 0)
{
_chartId = ChartID();
}
//
return _chartId;
}
//
// END Normalizations ...
//
+2 -2
View File
@@ -4248,7 +4248,7 @@ int GetYoungest(
//
int iAge = GetAge(iItem);
if (iAge > 0 &&
if (iAge >= 0 &&
(tmpAge == 0 || tmpAge > iAge))
{
//
@@ -4258,7 +4258,7 @@ int GetYoungest(
}
//
if (tmpAge > 0)
if (tmpAge >= 0)
{
//
result = tmpAge;