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
|