- Replaced standard library signal modules with custom implementations to allow for named patterns and improved voting. - Added new input parameters for module weights, allowing for optimization of individual signal contributions. - Enhanced the management of trades with new options for breakeven and management cut. - Introduced a mechanism for dynamic ranking of signal weights based on historical performance. - Improved initialization logic to ensure proper registration of filters and handling of trading conditions. - Added detailed logging for trading permissions and account status during initialization.
120 lines
6.5 KiB
MQL5
120 lines
6.5 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| ManagementNet.mqh |
|
|
//| AnimateDread |
|
|
//| |
|
|
//| THE ONE QUESTION NO RULE COULD ANSWER. |
|
|
//| |
|
|
//| A trade is +0.5R in front. Does it run to target, or give it all |
|
|
//| back to the stop? |
|
|
//| |
|
|
//| Measured on 9,770 resolved firings: 46.0% continue to +2R, 54.0% |
|
|
//| retrace. A balanced label on a large sample, and a PERFECT caller |
|
|
//| would be worth +0.540 R per firing - against a pooled deficit of |
|
|
//| -0.13 to -0.18 R. A quarter of it flips the sign of the strategy. |
|
|
//| |
|
|
//| WHY A MODEL AND NOT A RULE. Three rules were tried and all three |
|
|
//| lost money: an ATR trail (+150.67 -> +90.56, worse as it widened),|
|
|
//| a nearer target (-20.32), and a breakeven stop (-22.35 at +0.5R, |
|
|
//| monotonically worse the earlier it fired). They fail for one |
|
|
//| shared reason - a give-back and a pullback-before-a-run look |
|
|
//| IDENTICAL at the moment you must act. That is a classification |
|
|
//| problem wearing a rule's clothes, and a threshold on one number |
|
|
//| cannot separate two populations that overlap on that number. |
|
|
//| |
|
|
//| ⚠ IT DOES NOT PREDICT DIRECTION, and that is the point. Direction |
|
|
//| was measured dead in this project at bar level (rho 0.00-0.02) |
|
|
//| and every architecture thrown at it returned no information out |
|
|
//| of sample. This asks a CONDITIONAL question - given the move has |
|
|
//| already happened, does it extend or exhaust - which is a question |
|
|
//| about persistence and volatility, and volatility is the one thing |
|
|
//| here that has ever been predictable. |
|
|
//| |
|
|
//| ⚠ AND IT TRAINS ON THE CROSSING, NOT ON THE ENTRY. The features |
|
|
//| describe the bar where +0.5R was first touched: how fast it got |
|
|
//| there, how much pain came first, what the market was doing at |
|
|
//| that moment. Using the entry bar's state would be answering a |
|
|
//| different question with the wrong evidence. |
|
|
//| |
|
|
//| ⚠ maeR AS STORED IN THE JOURNAL IS LOOKAHEAD FOR THIS. It is the |
|
|
//| worst excursion over the WHOLE trade, including after the |
|
|
//| crossing, and it separates the two classes beautifully (0.51 vs |
|
|
//| 1.21) precisely because it contains the answer. The adverse |
|
|
//| excursion used here is measured only up TO the crossing bar. |
|
|
//+------------------------------------------------------------------+
|
|
#ifndef WARRIOR_MANAGEMENT_NET_MQH
|
|
#define WARRIOR_MANAGEMENT_NET_MQH
|
|
|
|
#include "WarriorNet.mqh"
|
|
|
|
#define MGMT_FEATURES 10
|
|
//--- The crossing this model is asked about, in R. Matched to the measurement above.
|
|
#define MGMT_TRIGGER_R 0.5
|
|
//--- How long a virtual trade may stay open before it is abandoned unlabelled.
|
|
#define MGMT_HORIZON 60
|
|
|
|
class CManagementNet
|
|
{
|
|
private:
|
|
CWarriorNet m_net;
|
|
bool m_ready;
|
|
string m_why;
|
|
|
|
public:
|
|
CManagementNet(void) : m_ready(false), m_why("not trained") {}
|
|
~CManagementNet(void) {}
|
|
|
|
bool Ready(void) const { return m_ready; }
|
|
string Why(void) const { return m_why; }
|
|
double AUC(void) const { return m_net.AUC(); }
|
|
|
|
static string FeatureName(const int i);
|
|
//--- P(this trade continues to target). <0 when there is no usable model.
|
|
double Score(double &x[]) { return m_ready ? m_net.Score(x) : -1.0; }
|
|
|
|
//--- TRAINED IN MEMORY, NEVER SERIALISED.
|
|
//---
|
|
//--- ALGLIB's MQL5 serializer under-allocates its output buffer and dies inside
|
|
//--- CSerializer::Stop() - "array out of range in ap.mqh (1996,17)" - which killed three of four
|
|
//--- H4 runs stone dead AFTER the model had trained and reported a perfectly good AUC. The same
|
|
//--- family of bug already bit DFSerialize on compressed forests in this repo.
|
|
//---
|
|
//--- Nothing is lost by skipping it: the fit is deferred and walk-forward by design, so it is
|
|
//--- rebuilt from history-so-far on every run regardless. A file would only be a cache of
|
|
//--- something cheap, bought at the price of a crash.
|
|
bool Train(CMatrixDouble &xy, const int rows, const string &names[])
|
|
{
|
|
//--- Embargo = the horizon. A virtual trade is a 60-bar window; rows closer than that to the
|
|
//--- boundary overlap the validation set's first rows. In the training matrix each ENTRY bar
|
|
//--- contributes two rows (long and short), so one horizon of bars is two horizons of rows.
|
|
m_ready = m_net.Train(xy, rows, MGMT_FEATURES, names, MGMT_HORIZON * 2);
|
|
m_why = m_net.Why();
|
|
return m_ready;
|
|
}
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
string CManagementNet::FeatureName(const int i)
|
|
{
|
|
switch(i)
|
|
{
|
|
//--- HOW IT GOT HERE. A move that reached +0.5R in one bar is a different animal from one
|
|
//--- that ground there over fifteen, and nothing about the entry bar can express that.
|
|
case 0: return "bars_to_cross";
|
|
case 1: return "mae_before_cross_r"; // pain paid BEFORE the gain - never after it
|
|
case 2: return "cross_speed_r_per_bar";
|
|
//--- WHAT THE MARKET IS DOING AT THE CROSSING. Persistence is the whole question, and these
|
|
//--- two are the direct measures of it: efficient and compounding, or cancelling.
|
|
case 3: return "er_at_cross";
|
|
case 4: return "vr_at_cross";
|
|
case 5: return "regime_at_cross";
|
|
//--- THE CROSSING BAR ITSELF. A wide bar closing at its extreme is an extension; a wide bar
|
|
//--- closing mid-range is exhaustion, and they look the same in R.
|
|
case 6: return "range_atr_at_cross";
|
|
case 7: return "close_in_bar_at_cross";
|
|
case 8: return "vol_rel_at_cross";
|
|
//--- Which way the trade is facing, so one model serves both sides rather than two models
|
|
//--- each trained on half the data.
|
|
case 9: return "is_long";
|
|
}
|
|
return "?";
|
|
}
|
|
#endif // WARRIOR_MANAGEMENT_NET_MQH
|