89 lines
6.6 KiB
Plaintext
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);
|
|
}
|
|
};
|