diff --git a/Indicator.struct.h b/Indicator.struct.h index 1a06ec762..1819695f3 100644 --- a/Indicator.struct.h +++ b/Indicator.struct.h @@ -55,6 +55,7 @@ struct IndicatorParams { int shift; // Shift (relative to the current bar, 0 - default). unsigned int max_params; // Max supported input params. ENUM_INDICATOR_TYPE itype; // Indicator type (e.g. INDI_RSI). + color indi_color; // Indicator color. ARRAY(DataParamEntry, input_params); // Indicator input params. string custom_indi_name; // Name of the indicator passed to iCustom() method. string symbol; // Symbol used by indicator. diff --git a/Indicators/Bitwise/Indi_Candle.mqh b/Indicators/Bitwise/Indi_Candle.mqh index d0845a979..306c018e2 100644 --- a/Indicators/Bitwise/Indi_Candle.mqh +++ b/Indicators/Bitwise/Indi_Candle.mqh @@ -44,11 +44,16 @@ class Indi_Candle : public Indicator { /** * Class constructor. */ - Indi_Candle(CandleParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) - : Indicator(_p, IndicatorDataParams::GetInstance(1, TYPE_INT, _idstype, IDATA_RANGE_RANGE, _indi_src_mode), _indi_src){}; + Indi_Candle(CandleParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : Indicator(_p, IndicatorDataParams::GetInstance(1, TYPE_INT, _idstype, IDATA_RANGE_RANGE, _indi_src_mode), + _indi_src){}; - Indi_Candle(int _shift = 0, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) - : Indicator(CandleParams(), IndicatorDataParams::GetInstance(1, TYPE_INT, _idstype, IDATA_RANGE_RANGE, _indi_src_mode), _indi_src) {}; + Indi_Candle(int _shift = 0, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : Indicator(CandleParams(), + IndicatorDataParams::GetInstance(1, TYPE_INT, _idstype, IDATA_RANGE_RANGE, _indi_src_mode), + _indi_src){}; /** * Returns possible data source types. It is a bit mask of ENUM_INDI_SUITABLE_DS_TYPE. diff --git a/Indicators/Bitwise/Indi_Pattern.mqh b/Indicators/Bitwise/Indi_Pattern.mqh index 5d3b3fff8..0c2d9d631 100644 --- a/Indicators/Bitwise/Indi_Pattern.mqh +++ b/Indicators/Bitwise/Indi_Pattern.mqh @@ -44,9 +44,16 @@ class Indi_Pattern : public Indicator { /** * Class constructor. */ - Indi_Pattern(IndiPatternParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData* _indi_src = NULL, int _indi_src_mode = 0) : Indicator(_p, IndicatorDataParams::GetInstance(5, TYPE_UINT, _idstype, IDATA_RANGE_BITWISE, _indi_src_mode), _indi_src) {} + Indi_Pattern(IndiPatternParams& _p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData* _indi_src = NULL, + int _indi_src_mode = 0) + : Indicator(_p, IndicatorDataParams::GetInstance(5, TYPE_UINT, _idstype, IDATA_RANGE_BITWISE, _indi_src_mode), + _indi_src) {} - Indi_Pattern(int _shift = 0, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData* _indi_src = NULL, int _indi_src_mode = 0) : Indicator(IndiPatternParams(), IndicatorDataParams::GetInstance(5, TYPE_UINT, _idstype, IDATA_RANGE_BITWISE, _indi_src_mode), _indi_src) {} + Indi_Pattern(int _shift = 0, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData* _indi_src = NULL, + int _indi_src_mode = 0) + : Indicator(IndiPatternParams(), + IndicatorDataParams::GetInstance(5, TYPE_UINT, _idstype, IDATA_RANGE_BITWISE, _indi_src_mode), + _indi_src) {} /** * Returns possible data source types. It is a bit mask of ENUM_INDI_SUITABLE_DS_TYPE. diff --git a/Indicators/Indi_ADX.mqh b/Indicators/Indi_ADX.mqh index a7e3c24ba..0c151c3f7 100644 --- a/Indicators/Indi_ADX.mqh +++ b/Indicators/Indi_ADX.mqh @@ -65,14 +65,18 @@ class Indi_ADX : public Indicator { : Indicator(_p, IndicatorDataParams::GetInstance(FINAL_INDI_ADX_LINE_ENTRY, TYPE_DOUBLE, _idstype, IDATA_RANGE_RANGE, _indi_src_mode), - _indi_src) {} + _indi_src) { + Init(); + } Indi_ADX(int _shift = 0, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) : Indicator(IndiADXParams(), IndicatorDataParams::GetInstance(FINAL_INDI_ADX_LINE_ENTRY, TYPE_DOUBLE, _idstype, IDATA_RANGE_RANGE, _indi_src_mode), - _indi_src) {} + _indi_src) { + Init(); + } /** * Returns possible data source types. It is a bit mask of ENUM_INDI_SUITABLE_DS_TYPE. */ diff --git a/Indicators/Indi_BWZT.mqh b/Indicators/Indi_BWZT.mqh index f8865996c..7ed2c0d16 100644 --- a/Indicators/Indi_BWZT.mqh +++ b/Indicators/Indi_BWZT.mqh @@ -65,7 +65,7 @@ class Indi_BWZT : public Indicator { /** * Initialize. */ - void Init() { Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES), FINAL_INDI_BWZT_MODE_ENTRY); } + void Init() {} public: /** diff --git a/Indicators/Indi_Drawer.mqh b/Indicators/Indi_Drawer.mqh index cd99852b7..2ef66b6f0 100644 --- a/Indicators/Indi_Drawer.mqh +++ b/Indicators/Indi_Drawer.mqh @@ -20,9 +20,6 @@ * */ -// Forward declaration. -struct IndicatorParams; - // Includes. #include "../DictStruct.mqh" #include "../Indicator.mqh" diff --git a/Indicators/Indi_Drawer.struct.h b/Indicators/Indi_Drawer.struct.h index 8af85c11a..473209d9f 100644 --- a/Indicators/Indi_Drawer.struct.h +++ b/Indicators/Indi_Drawer.struct.h @@ -27,6 +27,7 @@ // Includes. #include "../Indicator.struct.h" +#include "../SerializerNode.enum.h" // Structs. diff --git a/Indicators/Indi_Pivot.mqh b/Indicators/Indi_Pivot.mqh index 846bf1b99..d49539d91 100644 --- a/Indicators/Indi_Pivot.mqh +++ b/Indicators/Indi_Pivot.mqh @@ -47,7 +47,10 @@ class Indi_Pivot : public Indicator { /** * Initialize. */ - void Init() { Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES), 9); } + void Init() {} + + protected: + /* Protected methods */ public: /** diff --git a/Indicators/OHLC/Indi_OHLC.mqh b/Indicators/OHLC/Indi_OHLC.mqh index a0738567c..eb4f8a997 100644 --- a/Indicators/OHLC/Indi_OHLC.mqh +++ b/Indicators/OHLC/Indi_OHLC.mqh @@ -49,7 +49,18 @@ class Indi_OHLC : public Indicator { /** * Class constructor. */ - Indi_OHLC(IndiOHLCParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) : Indicator(_p, IndicatorDataParams::GetInstance(FINAL_INDI_OHLC_MODE_ENTRY, TYPE_DOUBLE, _idstype, IDATA_RANGE_PRICE, _indi_src_mode), _indi_src){}; Indi_OHLC(int _shift = 0, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) : Indicator(IndiOHLCParams(), IndicatorDataParams::GetInstance(FINAL_INDI_OHLC_MODE_ENTRY, TYPE_DOUBLE, _idstype, IDATA_RANGE_PRICE, _indi_src_mode), _indi_src) {}; + Indi_OHLC(IndiOHLCParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : Indicator(_p, + IndicatorDataParams::GetInstance(FINAL_INDI_OHLC_MODE_ENTRY, TYPE_DOUBLE, _idstype, IDATA_RANGE_PRICE, + _indi_src_mode), + _indi_src){}; + Indi_OHLC(int _shift = 0, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : Indicator(IndiOHLCParams(), + IndicatorDataParams::GetInstance(FINAL_INDI_OHLC_MODE_ENTRY, TYPE_DOUBLE, _idstype, IDATA_RANGE_PRICE, + _indi_src_mode), + _indi_src){}; /** * Returns possible data source types. It is a bit mask of ENUM_INDI_SUITABLE_DS_TYPE. */ diff --git a/Indicators/Price/Indi_Price.mqh b/Indicators/Price/Indi_Price.mqh index bbe3533b8..76299b153 100644 --- a/Indicators/Price/Indi_Price.mqh +++ b/Indicators/Price/Indi_Price.mqh @@ -48,7 +48,15 @@ class Indi_Price : public Indicator { /** * Class constructor. */ - Indi_Price(PriceIndiParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) : Indicator(_p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_PRICE, _indi_src_mode), _indi_src){}; Indi_Price(int _shift = 0, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) : Indicator(PriceIndiParams(), IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_PRICE, _indi_src_mode), _indi_src) {}; + Indi_Price(PriceIndiParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : Indicator(_p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_PRICE, _indi_src_mode), + _indi_src){}; + Indi_Price(int _shift = 0, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : Indicator(PriceIndiParams(), + IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_PRICE, _indi_src_mode), + _indi_src){}; /** * Returns possible data source types. It is a bit mask of ENUM_INDI_SUITABLE_DS_TYPE. */ diff --git a/Indicators/Special/Indi_Math.mqh b/Indicators/Special/Indi_Math.mqh index 3977a5972..f6bcb890c 100644 --- a/Indicators/Special/Indi_Math.mqh +++ b/Indicators/Special/Indi_Math.mqh @@ -75,8 +75,15 @@ class Indi_Math : public Indicator { /** * Class constructor. */ - Indi_Math(IndiMathParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_INDICATOR, IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) : Indicator(_p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), _indi_src){}; - Indi_Math(int _shift = 0, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_INDICATOR, IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) : Indicator(IndiMathParams(), IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), _indi_src) {}; + Indi_Math(IndiMathParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_INDICATOR, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : Indicator(_p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src){}; + Indi_Math(int _shift = 0, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_INDICATOR, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : Indicator(IndiMathParams(), + IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src){}; /** * Returns possible data source types. It is a bit mask of ENUM_INDI_SUITABLE_DS_TYPE. */ diff --git a/Instances.h b/Instances.h index fee38cb80..9f1812fa5 100644 --- a/Instances.h +++ b/Instances.h @@ -30,6 +30,10 @@ #pragma once #endif +// Prevents processing this includes file multiple times. +#ifndef INSTANCES_H +#define INSTANCES_H + #include "Dict.mqh" #include "Util.h" @@ -49,3 +53,5 @@ class Instances { template T* Instances::instances[]; + +#endif // INSTANCES_MQH diff --git a/Storage/ValueStorage.h b/Storage/ValueStorage.h index 195a5ee29..6c7979ba0 100644 --- a/Storage/ValueStorage.h +++ b/Storage/ValueStorage.h @@ -314,4 +314,4 @@ int iPeak(ValueStorage &_price, int _count, int _start, ENUM_IPEAK _type return _price_size - _peak_idx - 1; } -#endif // STRATEGY_MQH +#endif // VALUE_STORAGE_H diff --git a/Strategy.mqh b/Strategy.mqh index c6553b5e1..24fab7aa9 100644 --- a/Strategy.mqh +++ b/Strategy.mqh @@ -884,7 +884,7 @@ class Strategy : public Taskable { if (METHOD(_method, 6)) _result &= !trade REF_DEREF Check( TRADE_COND_ACCOUNT, _method > 0 ? ACCOUNT_COND_EQUITY_01PC_LOW : ACCOUNT_COND_EQUITY_01PC_HIGH); // 64 - */ + */ // if (METHOD(_method, 5)) _result &= Trade().IsRoundNumber(_cmd); // if (METHOD(_method, 6)) _result &= Trade().IsHedging(_cmd); _method = _method > 0 ? _method : !_method; @@ -996,7 +996,7 @@ class Strategy : public Taskable { _result |= _result || trade REF_DEREF Check(TRADE_COND_ACCOUNT, _method > 0 ? ACCOUNT_COND_EQUITY_01PC_HIGH : ACCOUNT_COND_EQUITY_01PC_LOW); // 64 - */ + */ // if (METHOD(_method, 7)) _result |= _result || Trade().IsRoundNumber(_cmd); // if (METHOD(_method, 8)) _result |= _result || Trade().IsHedging(_cmd); _method = _method > 0 ? _method : !_method; @@ -1090,12 +1090,19 @@ class Strategy : public Taskable { bool AddTask(TaskEntry &_tentry) { bool _is_valid = _tentry.IsValid(); if (_is_valid) { - TaskObject _taskobj(_tentry, THIS_PTR, THIS_PTR); - tasks.Add(&_taskobj); + tasks.Add(new TaskObject(_tentry, THIS_PTR, THIS_PTR)); } return _is_valid; } + /** + * Add task object. + */ + template + bool AddTaskObject(TaskObject *_tobj) { + return tasks.Add(_tobj); + } + /** * Process tasks. */ diff --git a/SummaryReport.mqh b/SummaryReport.mqh index 4ce40d043..964a52b98 100644 --- a/SummaryReport.mqh +++ b/SummaryReport.mqh @@ -30,291 +30,291 @@ * Class to provide a summary report. */ class SummaryReport { - protected: - // Variables. - double init_deposit; - double summary_profit; - double gross_profit; - double gross_loss; - double max_profit; - double min_profit; - double con_profit1; - double con_profit2; - double con_loss1; - double con_loss2; - double max_loss; - double max_dd; - double max_dd_pct; - double rel_dd_pct; - double rel_dd; - double expected_payoff; - double profit_factor; - double abs_dd; - int summary_trades; - int profit_trades; - int loss_trades; - int short_trades; - int long_trades; - int win_short_trades; - int win_long_trades; - int con_profit_trades1; - int con_profit_trades2; - int con_loss_trades1; - int con_loss_trades2; - int avg_con_wins; - int avg_con_losses; + protected: + // Variables. + double init_deposit; + double summary_profit; + double gross_profit; + double gross_loss; + double max_profit; + double min_profit; + double con_profit1; + double con_profit2; + double con_loss1; + double con_loss2; + double max_loss; + double max_dd; + double max_dd_pct; + double rel_dd_pct; + double rel_dd; + double expected_payoff; + double profit_factor; + double abs_dd; + int summary_trades; + int profit_trades; + int loss_trades; + int short_trades; + int long_trades; + int win_short_trades; + int win_long_trades; + int con_profit_trades1; + int con_profit_trades2; + int con_loss_trades1; + int con_loss_trades2; + int avg_con_wins; + int avg_con_losses; - double init_balance; + double init_balance; - public: - /** - * Default constructor. - */ + public: + /** + * Default constructor. + */ SummaryReport() { InitVars(AccountMt::AccountBalance()); } - /** - * Constructor to initialize starting balance. - */ + /** + * Constructor to initialize starting balance. + */ SummaryReport(double deposit) { InitVars(deposit); } - /** - * Constructor to initialize starting balance. - */ - void InitVars(double deposit = 0) { - init_deposit = deposit; - max_loss = deposit; - summary_profit = 0.0; - gross_profit = 0.0; - gross_loss = 0.0; - max_profit = 0.0; - min_profit = 0.0; - con_profit1 = 0.0; - con_profit2 = 0.0; - con_loss1 = 0.0; - con_loss2 = 0.0; - max_dd = 0.0; - max_dd_pct = 0.0; - rel_dd_pct = 0.0; - rel_dd = 0.0; - expected_payoff = 0.0; - profit_factor = 0.0; - abs_dd = 0.0; - summary_trades = 0; - profit_trades = 0; - loss_trades = 0; - short_trades = 0; - long_trades = 0; - win_short_trades = 0; - win_long_trades = 0; - con_profit_trades1 = 0; - con_profit_trades2 = 0; - con_loss_trades1 = 0; - con_loss_trades2 = 0; - avg_con_wins = 0; - avg_con_losses = 0; - } + /** + * Constructor to initialize starting balance. + */ + void InitVars(double deposit = 0) { + init_deposit = deposit; + max_loss = deposit; + summary_profit = 0.0; + gross_profit = 0.0; + gross_loss = 0.0; + max_profit = 0.0; + min_profit = 0.0; + con_profit1 = 0.0; + con_profit2 = 0.0; + con_loss1 = 0.0; + con_loss2 = 0.0; + max_dd = 0.0; + max_dd_pct = 0.0; + rel_dd_pct = 0.0; + rel_dd = 0.0; + expected_payoff = 0.0; + profit_factor = 0.0; + abs_dd = 0.0; + summary_trades = 0; + profit_trades = 0; + loss_trades = 0; + short_trades = 0; + long_trades = 0; + win_short_trades = 0; + win_long_trades = 0; + con_profit_trades1 = 0; + con_profit_trades2 = 0; + con_loss_trades1 = 0; + con_loss_trades2 = 0; + avg_con_wins = 0; + avg_con_losses = 0; + } - /** - * Get initial deposit. - */ - double GetInitDeposit() { - static double deposit = 0; - if (deposit > 0) { - return deposit; + /** + * Get initial deposit. + */ + double GetInitDeposit() { + static double deposit = 0; + if (deposit > 0) { + return deposit; } else if (!Terminal::IsRealtime() && init_deposit > 0) { - deposit = init_deposit; - } else { - deposit = AccountMt::CalcInitDeposit(); + deposit = init_deposit; + } else { + deposit = AccountMt::CalcInitDeposit(); + } + return (deposit); } - return (deposit); - } - /** - * Calculates summary details. - */ - void CalculateSummary() { - int sequence = 0, profitseqs = 0, loss_seqs = 0; - double sequential = 0.0, prev_profit = EMPTY_VALUE, dd_pct, drawdown; - double max_peak = init_deposit, min_peak = init_deposit, balance = init_deposit; - int trades_total = TradeHistoryStatic::HistoryOrdersTotal(); - double profit; + /** + * Calculates summary details. + */ + void CalculateSummary() { + int sequence = 0, profitseqs = 0, loss_seqs = 0; + double sequential = 0.0, prev_profit = EMPTY_VALUE, dd_pct, drawdown; + double max_peak = init_deposit, min_peak = init_deposit, balance = init_deposit; + int trades_total = TradeHistoryStatic::HistoryOrdersTotal(); + double profit; - // Initialize summaries. - InitVars(init_deposit); + // Initialize summaries. + InitVars(init_deposit); - for (int i = 0; i < trades_total; i++) { - if (!Order::TryOrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) { - continue; - } - int type = Order::OrderType(); - // Initial balance not considered. - if (i == 0 && type == ACC_OP_BALANCE) continue; - // Calculate profit. - profit = OrderStatic::Profit() + OrderStatic::Commission() + Order::OrderSwap(); - balance += profit; - // Drawdown check. - if (max_peak < balance) { - drawdown = max_peak - min_peak; - if (max_peak != 0.0) { - dd_pct = drawdown / max_peak * 100.0; - if (rel_dd_pct < dd_pct) { - rel_dd_pct = dd_pct; - rel_dd = drawdown; - } + for (int i = 0; i < trades_total; i++) { + if (!Order::TryOrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) { + continue; } - if (max_dd < drawdown) { - max_dd = drawdown; - max_dd_pct = max_peak != 0.0 ? max_dd / max_peak * 100.0 : 100.0; + int type = Order::OrderType(); + // Initial balance not considered. + if (i == 0 && type == ACC_OP_BALANCE) continue; + // Calculate profit. + profit = OrderStatic::Profit() + OrderStatic::Commission() + Order::OrderSwap(); + balance += profit; + // Drawdown check. + if (max_peak < balance) { + drawdown = max_peak-min_peak; + if (max_peak != 0.0) { + dd_pct = drawdown / max_peak * 100.0; + if (rel_dd_pct < dd_pct) { + rel_dd_pct = dd_pct; + rel_dd = drawdown; + } + } + if (max_dd < drawdown) { + max_dd = drawdown; + max_dd_pct = max_peak != 0.0 ? max_dd / max_peak * 100.0 : 100.0; + } + max_peak = balance; + min_peak = balance; } - max_peak = balance; - min_peak = balance; - } - if (min_peak > balance) min_peak = balance; - if (max_loss > balance) max_loss = balance; - // Market orders only. - if (type != ORDER_TYPE_BUY && type != ORDER_TYPE_SELL) continue; - // Calculate profit in points. - // profit = (OrderClosePrice() - OrderOpenPrice()) / MarketInfo(OrderSymbol(), MODE_POINT); - summary_profit += profit; - summary_trades++; - if (type == ORDER_TYPE_BUY) { - long_trades++; + if (min_peak > balance) min_peak = balance; + if (max_loss > balance) max_loss = balance; + // Market orders only. + if (type != ORDER_TYPE_BUY && type != ORDER_TYPE_SELL) continue; + // Calculate profit in points. + // profit = (OrderClosePrice() - OrderOpenPrice()) / MarketInfo(OrderSymbol(), MODE_POINT); + summary_profit += profit; + summary_trades++; + if (type == ORDER_TYPE_BUY) { + long_trades++; } else if (type == ORDER_TYPE_SELL) { - short_trades++; - } - if (profit < 0) { - // Loss trades. - loss_trades++; - gross_loss += profit; - if (min_profit > profit) min_profit = profit; - // Fortune changed. - if (prev_profit != EMPTY_VALUE && prev_profit >= 0) { + short_trades++; + } + if (profit < 0) { + // Loss trades. + loss_trades++; + gross_loss += profit; + if (min_profit > profit) min_profit = profit; + // Fortune changed. + if (prev_profit != EMPTY_VALUE && prev_profit >= 0) { if (con_profit_trades1 < sequence || (con_profit_trades1 == sequence && con_profit2 < sequential)) { - con_profit_trades1 = sequence; - con_profit1 = sequential; - } + con_profit_trades1 = sequence; + con_profit1 = sequential; + } if (con_profit2 < sequential || (con_profit2 == sequential && con_profit_trades1 < sequence)) { - con_profit2 = sequential; - con_profit_trades2 = sequence; + con_profit2 = sequential; + con_profit_trades2 = sequence; + } + profitseqs++; + avg_con_wins += sequence; + sequence = 0; + sequential = 0.0; } - profitseqs++; - avg_con_wins += sequence; - sequence = 0; - sequential = 0.0; - } - } else { - // Profit trades (profit >= 0). - profit_trades++; - if (type == ORDER_TYPE_BUY) win_long_trades++; - if (type == ORDER_TYPE_SELL) win_short_trades++; - gross_profit += profit; - if (max_profit < profit) max_profit = profit; - // Fortune changed. - if (prev_profit != EMPTY_VALUE && prev_profit < 0) { + } else { + // Profit trades (profit >= 0). + profit_trades++; + if (type == ORDER_TYPE_BUY) win_long_trades++; + if (type == ORDER_TYPE_SELL) win_short_trades++; + gross_profit += profit; + if (max_profit < profit) max_profit = profit; + // Fortune changed. + if (prev_profit != EMPTY_VALUE && prev_profit < 0) { if (con_loss_trades1 < sequence || (con_loss_trades1 == sequence && con_loss2 > sequential)) { + con_loss_trades1 = sequence; + con_loss1 = sequential; + } + if (con_loss2 > sequential || (con_loss2 == sequential && con_loss_trades1 < sequence)) { + con_loss2 = sequential; + con_loss_trades2 = sequence; + } + loss_seqs++; + avg_con_losses += sequence; + sequence = 0; + sequential = 0.0; + } + } + sequence++; + sequential += profit; + prev_profit = profit; + } + // Final drawdown check. + drawdown = max_peak - min_peak; + if (max_peak != 0.0) { + dd_pct = drawdown / max_peak * 100.0; + if (rel_dd_pct < dd_pct) { + rel_dd_pct = dd_pct; + rel_dd = drawdown; + } + } + if (max_dd < drawdown) { + max_dd = drawdown; + max_dd_pct = max_peak != 0 ? max_dd / max_peak * 100.0 : 100.0; + } + // Consider last trade. + if (prev_profit != EMPTY_VALUE) { + profit = prev_profit; + if (profit < 0) { + if (con_loss_trades1 < sequence || (con_loss_trades1 == sequence && con_loss2 > sequential)) { con_loss_trades1 = sequence; con_loss1 = sequential; } - if (con_loss2 > sequential || (con_loss2 == sequential && con_loss_trades1 < sequence)) { + if (con_loss2 > sequential || (con_loss2 == sequential && con_loss_trades1 < sequence)) { con_loss2 = sequential; con_loss_trades2 = sequence; } loss_seqs++; avg_con_losses += sequence; - sequence = 0; - sequential = 0.0; - } - } - sequence++; - sequential += profit; - prev_profit = profit; - } - // Final drawdown check. - drawdown = max_peak - min_peak; - if (max_peak != 0.0) { - dd_pct = drawdown / max_peak * 100.0; - if (rel_dd_pct < dd_pct) { - rel_dd_pct = dd_pct; - rel_dd = drawdown; - } - } - if (max_dd < drawdown) { - max_dd = drawdown; - max_dd_pct = max_peak != 0 ? max_dd / max_peak * 100.0 : 100.0; - } - // Consider last trade. - if (prev_profit != EMPTY_VALUE) { - profit = prev_profit; - if (profit < 0) { - if (con_loss_trades1 < sequence || (con_loss_trades1 == sequence && con_loss2 > sequential)) { - con_loss_trades1 = sequence; - con_loss1 = sequential; - } - if (con_loss2 > sequential || (con_loss2 == sequential && con_loss_trades1 < sequence)) { - con_loss2 = sequential; - con_loss_trades2 = sequence; - } - loss_seqs++; - avg_con_losses += sequence; } else { if (con_profit_trades1 < sequence || (con_profit_trades1 == sequence && con_profit2 < sequential)) { - con_profit_trades1 = sequence; - con_profit1 = sequential; - } + con_profit_trades1 = sequence; + con_profit1 = sequential; + } if (con_profit2 < sequential || (con_profit2 == sequential && con_profit_trades1 < sequence)) { - con_profit2 = sequential; - con_profit_trades2 = sequence; + con_profit2 = sequential; + con_profit_trades2 = sequence; + } + profitseqs++; + avg_con_wins += sequence; } - profitseqs++; - avg_con_wins += sequence; } + // Collecting done. + double dnum, profitkoef = 0.0, losskoef = 0.0, avg_profit = 0.0, avgloss = 0.0; + // Average consecutive wins and losses. + dnum = avg_con_wins; + avg_con_wins = profitseqs > 0 ? (int) (dnum / profitseqs + 0.5) : 0; + dnum = avg_con_losses; + avg_con_losses = loss_seqs > 0 ? (int) (dnum / loss_seqs + 0.5) : 0; + // Absolute values. + if (gross_loss < 0.0) gross_loss *=- 1.0; + if (min_profit < 0.0) min_profit *=- 1.0; + if (con_loss1 < 0.0) con_loss1 *=- 1.0; + if (con_loss2 < 0.0) con_loss2 *=- 1.0; + profit_factor = gross_loss > 0.0 ? gross_profit / gross_loss : 0.0; + // Expected payoff. + avg_profit = profit_trades > 0 ? gross_profit / profit_trades : 0; + avgloss = loss_trades > 0 ? gross_loss / loss_trades : 0; + if (summary_trades > 0) { + profitkoef = 1.0 * profit_trades / summary_trades; + losskoef = 1.0 * loss_trades / summary_trades; + expected_payoff = profitkoef * avg_profit - losskoef * avgloss; + } + // Absolute drawdown. + abs_dd = init_deposit - max_loss; } - // Collecting done. - double dnum, profitkoef = 0.0, losskoef = 0.0, avg_profit = 0.0, avgloss = 0.0; - // Average consecutive wins and losses. - dnum = avg_con_wins; - avg_con_wins = profitseqs > 0 ? (int)(dnum / profitseqs + 0.5) : 0; - dnum = avg_con_losses; - avg_con_losses = loss_seqs > 0 ? (int)(dnum / loss_seqs + 0.5) : 0; - // Absolute values. - if (gross_loss < 0.0) gross_loss *= -1.0; - if (min_profit < 0.0) min_profit *= -1.0; - if (con_loss1 < 0.0) con_loss1 *= -1.0; - if (con_loss2 < 0.0) con_loss2 *= -1.0; - profit_factor = gross_loss > 0.0 ? gross_profit / gross_loss : 0.0; - // Expected payoff. - avg_profit = profit_trades > 0 ? gross_profit / profit_trades : 0; - avgloss = loss_trades > 0 ? gross_loss / loss_trades : 0; - if (summary_trades > 0) { - profitkoef = 1.0 * profit_trades / summary_trades; - losskoef = 1.0 * loss_trades / summary_trades; - expected_payoff = profitkoef * avg_profit - losskoef * avgloss; - } - // Absolute drawdown. - abs_dd = init_deposit - max_loss; - } - /** - * Return summary report. - */ - string GetReport(string sep = "\n", string _currency = "") { - string output = ""; - _currency = _currency != "" ? _currency : AccountInfoString(ACCOUNT_CURRENCY); - output += StringFormat("Currency pair symbol: %s", _Symbol) + sep; - output += StringFormat("Initial deposit: %.2f %s", GetInitDeposit(), _currency) + sep; - output += StringFormat("Total net profit: %.2f %s", summary_profit, _currency) + sep; - output += StringFormat("Gross profit: %.2f %s", gross_profit, _currency) + sep; - output += StringFormat("Gross loss: %.2f %s", gross_loss, _currency) + sep; - output += StringFormat("Absolute drawdown: %.2f %s", abs_dd, _currency) + sep; + /** + * Return summary report. + */ + string GetReport(string sep = "\n", string _currency = "") { + string output = ""; + _currency = _currency != "" ? _currency : AccountInfoString(ACCOUNT_CURRENCY); + output += StringFormat("Currency pair symbol: %s", _Symbol) + sep; + output += StringFormat("Initial deposit: %.2f %s", GetInitDeposit(), _currency) + sep; + output += StringFormat("Total net profit: %.2f %s", summary_profit, _currency) + sep; + output += StringFormat("Gross profit: %.2f %s", gross_profit, _currency) + sep; + output += StringFormat("Gross loss: %.2f %s", gross_loss, _currency) + sep; + output += StringFormat("Absolute drawdown: %.2f %s", abs_dd, _currency) + sep; output += StringFormat("Maximal drawdown: %.1f %s (%.1f%%)", max_dd, _currency, max_dd_pct) + sep; output += StringFormat("Relative drawdown: (%.1f%%) %.1f %s", rel_dd_pct, rel_dd, _currency) + sep; - output += StringFormat("Profit factor: %.2f", profit_factor) + sep; - output += StringFormat("Expected payoff: %.2f", expected_payoff) + sep; - output += StringFormat("Trades total %d", summary_trades) + sep; + output += StringFormat("Profit factor: %.2f", profit_factor) + sep; + output += StringFormat("Expected payoff: %.2f", expected_payoff) + sep; + output += StringFormat("Trades total %d", summary_trades) + sep; output += StringFormat("Short positions (won %%): %d (%.1f%%)", short_trades, short_trades ? 100.0 * win_short_trades / short_trades : 0) + sep; @@ -327,22 +327,22 @@ class SummaryReport { output += StringFormat("Loss trades (%% of total): %d (%.1f%%)", loss_trades, loss_trades ? 100.0 * loss_trades / summary_trades : 0) + sep; - output += StringFormat("Largest profit trade: %.2f", max_profit) + sep; - output += StringFormat("Largest loss trade: %.2f", -min_profit) + sep; + output += StringFormat("Largest profit trade: %.2f", max_profit) + sep; + output += StringFormat("Largest loss trade: %.2f", -min_profit) + sep; output += StringFormat("Average profit trade: %.2f", profit_trades ? gross_profit / profit_trades : 0) + sep; output += StringFormat("Average loss trade: %.2f", loss_trades ? -gross_loss / loss_trades : 0) + sep; - output += StringFormat("Average consecutive wins: %.2f", avg_con_wins) + sep; - output += StringFormat("Average consecutive losses: %.2f", avg_con_losses) + sep; + output += StringFormat("Average consecutive wins: %.2f", avg_con_wins) + sep; + output += StringFormat("Average consecutive losses: %.2f", avg_con_losses) + sep; output += StringFormat("Maximum consecutive wins (profit in money): %d (%.2f)", con_profit_trades1, con_profit1) + sep; - output += StringFormat("Maximum consecutive losses (loss in money): %d (%.2f)", con_loss_trades1, -con_loss1) + sep; + output += StringFormat("Maximum consecutive losses (loss in money): %d (%.2f)", con_loss_trades1, -con_loss1) + sep; output += StringFormat("Maximal consecutive profit (count of wins): %.2f (%d)", con_profit2, con_profit_trades2) + sep; - output += StringFormat("Maximal consecutive loss (count of losses): %.2f (%d)", con_loss2, con_loss_trades2) + sep; - return output; - } + output += StringFormat("Maximal consecutive loss (count of losses): %.2f (%d)", con_loss2, con_loss_trades2) + sep; + return output; + } }; diff --git a/Trade.mqh b/Trade.mqh index 3faeafeae..513ebf695 100644 --- a/Trade.mqh +++ b/Trade.mqh @@ -203,7 +203,10 @@ class Trade : public Taskable { _request.symbol = GetSource() PTR_DEREF GetSymbol(); _request.price = GetSource() PTR_DEREF GetOpenOffer(_type); _request.type = _type; +#ifndef __MQL4__ + // Filling modes not supported under MQL4. _request.type_filling = Order::GetOrderFilling(_request.symbol); +#endif _request.volume = _volume > 0 ? _volume : tparams.Get(TRADE_PARAM_LOT_SIZE); _request.volume = NormalizeLots(fmax(_request.volume, GetSource() PTR_DEREF GetSymbolProps().GetVolumeMin())); @@ -1395,7 +1398,7 @@ HistorySelect(0, TimeCurrent()); // Select history for access. && Terminal::CheckPermissionToTrade() // Check if auto trading is enabled. && (Terminal::IsRealtime() && !Terminal::IsExpertEnabled())); -/* Chart checks */ + /* Chart checks */ #ifdef __debug__ Print("Trade: Bars in data source: ", GetSource() PTR_DEREF GetBars(), ", minimum required bars: ", tparams.GetBarsMin()); @@ -1764,12 +1767,19 @@ HistorySelect(0, TimeCurrent()); // Select history for access. bool AddTask(TaskEntry &_tentry) { bool _is_valid = _tentry.IsValid(); if (_is_valid) { - TaskObject _taskobj(_tentry, THIS_PTR, THIS_PTR); - tasks.Add(&_taskobj); + tasks.Add(new TaskObject(_tentry, THIS_PTR, THIS_PTR)); } return _is_valid; } + /** + * Add task object. + */ + template + bool AddTaskObject(TaskObject *_tobj) { + return tasks.Add(_tobj); + } + /** * Process tasks. */ diff --git a/tests/CompileTest.mq5 b/tests/CompileTest.mq5 index 7b3e1e7bf..d8666aac8 100644 --- a/tests/CompileTest.mq5 +++ b/tests/CompileTest.mq5 @@ -35,6 +35,9 @@ #include "../3D/Frontends/MT5Frontend.h" #endif +// Forward declaration. +struct IndicatorParams; + // Includes. #include "../Account/AccountMt.h" #include "../Array.mqh" @@ -64,7 +67,7 @@ #include "../Indicator.mqh" #include "../IndicatorBase.h" #include "../IndicatorData.mqh" -#include "../Inet.mqh" +// #include "../Inet.mqh" #include "../Log.mqh" #include "../MD5.mqh" #include "../Storage/IValueStorage.h" @@ -81,7 +84,7 @@ #include "../Order.mqh" #include "../Orders.mqh" #include "../Pattern.mqh" -#include "../Profiler.mqh" +// #include "../Profiler.mqh" #include "../Redis.mqh" #include "../Refs.mqh" #include "../Registry.mqh" @@ -124,7 +127,6 @@ // #include "../Tester.mqh" // @removeme #include "../Storage/ValueStorage.h" // #include "../Tests.mqh" // @removeme -#include "../Ticker.mqh" #include "../Timer.mqh" #include "../Trade.mqh" #include "../Util.h" diff --git a/tests/DrawIndicatorTest.mq5 b/tests/DrawIndicatorTest.mq5 index 856d550aa..69779aecc 100644 --- a/tests/DrawIndicatorTest.mq5 +++ b/tests/DrawIndicatorTest.mq5 @@ -136,6 +136,14 @@ bool InitIndicators() { // ma_on_price_params.SetDataSource(indi_price_4_ma, true, INDI_PRICE_MODE_OPEN); ma_on_price_params.SetIndicatorType(INDI_MA_ON_PRICE); Platform::AddWithDefaultBindings(new Indi_MA(ma_on_price_params, indi_price_4_ma)); + + // Relative Strength Index (RSI) over Price indicator. + PriceIndiParams price_params_4_rsi(); + IndicatorData *indi_price_4_rsi = new Indi_Price(price_params_4_rsi); + IndiRSIParams rsi_on_price_params(); + rsi_on_price_params.SetDraw(clrBisque, 1); + IndicatorBase *indi_rsi_on_price = new Indi_RSI(rsi_on_price_params, IDATA_INDICATOR, indi_price_4_rsi); + indis.Set(INDI_RSI_ON_PRICE, indi_rsi_on_price); */ // We'll be drawing all indicators' values on the chart. @@ -154,9 +162,9 @@ bool PrintIndicators(string _prefix = "") { ResetLastError(); for (DictIterator> iter = Platform::GetIndicators() PTR_DEREF Begin(); iter.IsValid(); ++iter) { - IndicatorBase *_indi = iter.Value().Ptr(); + IndicatorData *_indi = iter.Value().Ptr(); if (_indi.Get(STRUCT_ENUM(IndicatorState, INDICATOR_STATE_PROP_IS_READY))) { - // PrintFormat("%s: %s: %s", _prefix, _indi.GetName(), _indi.ToString()); + PrintFormat("%s: %s: %s", _prefix, _indi.GetName(), _indi.ToString()); } } return GetLastError() == ERR_NO_ERROR; diff --git a/tests/IndicatorsTest.mq5 b/tests/IndicatorsTest.mq5 index 7ac3e1b03..4aca8c09e 100644 --- a/tests/IndicatorsTest.mq5 +++ b/tests/IndicatorsTest.mq5 @@ -25,8 +25,8 @@ */ // Defines. -//#define __debug__ // Enables debug. -//#define __debug_verbose__ +// #define __debug__ // Enables debug. +// #define __debug_verbose__ // Forward declaration. struct DataParamEntry; @@ -99,7 +99,7 @@ void OnTick() { if (_candles PTR_DEREF IsNewBar()) { if (_candles PTR_DEREF GetBarIndex() > 200) { ExpertRemove(); - } + } if (indis.Size() == 0) { return;