Files
include/OLAP/OLAPTradesCustom.mqh
2025-02-07 19:13:59 +03:30

89 lines
6.6 KiB
Plaintext

//+------------------------------------------------------------------+
//| OLAPTradesCustom.mqh |
//| Copyright © 2020, Marketeer |
//| https://www.mql5.com/en/users/marketeer |
//| Online Analytical Processing of trading hypercubes |
//| https://www.mql5.com/en/articles/6602 |
//| https://www.mql5.com/en/articles/6603 |
//| https://www.mql5.com/en/articles/7535 |
//| https://www.mql5.com/en/articles/7656 |
//| rev. 25.02.2020 |
//+------------------------------------------------------------------+
class CustomTradeRecord;
#define RECORD_CLASS CustomTradeRecord
#include "OLAPTrades.mqh"
class CustomTradeRecord: public TradeRecord
{
private:
// Start-up time announcement of custom fields specialization
class CustomFieldsDescription
{
private:
CustomFieldsDescription()
{
Print("Custom fields processing attached:");
Print("FIELD_CUSTOM1 == Single Trade MFE (%)");
Print("FIELD_CUSTOM2 == Single Trade MAE (%)");
}
public:
static CustomFieldsDescription *instantiate()
{
static CustomFieldsDescription instance;
return &instance;
}
};
public:
CustomTradeRecord(): TradeRecord()
{
}
CustomTradeRecord(const double balance): TradeRecord(balance)
{
fillCustomFields();
}
// calculate MFE/MAE in percents
virtual void fillCustomFields() override
{
static CustomFieldsDescription *legend = CustomFieldsDescription::instantiate();
double positiveExcursion = 0, negativeExcursion = 0;
string symbol = symbols[(int)get(FIELD_SYMBOL)];
int t1 = iBarShift(symbol, _Period, (datetime)get(FIELD_OPEN_DATETIME), false);
int t2 = iBarShift(symbol, _Period, (datetime)get(FIELD_CLOSE_DATETIME), false);
int type = (int)get(FIELD_TYPE);
double open = get(FIELD_OPEN_PRICE);
double close = get(FIELD_CLOSE_PRICE);
for(int t = t1; t >= t2; t--)
{
if(type == OP_BUY)
{
positiveExcursion = MathMax(positiveExcursion, MathMax((iHigh(symbol, _Period, t) - close), 0) / close);
negativeExcursion = MathMin(negativeExcursion, MathMin((iLow(symbol, _Period, t) - open), 0) / open);
}
else if(type == OP_SELL)
{
positiveExcursion = MathMax(positiveExcursion, MathMax((close - iLow(symbol, _Period, t)), 0) / close);
negativeExcursion = MathMin(negativeExcursion, MathMin((open - iHigh(symbol, _Period, t)), 0) / open);
}
}
set(TRADE_RECORD_FIELDS::FIELD_CUSTOM_1, positiveExcursion * 100);
set(TRADE_RECORD_FIELDS::FIELD_CUSTOM_2, negativeExcursion * 100);
}
virtual string legend(const int index) const override
{
if(index == TRADE_RECORD_FIELDS::FIELD_CUSTOM_1) return "MFE per trade(%)";
else
if(index == TRADE_RECORD_FIELDS::FIELD_CUSTOM_2) return "MAE per trade(%)";
return TradeRecord::legend(index);
}
};