370 行
16 KiB
MQL5
370 行
16 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| ADIndicatorTuner.mqh |
|
||
|
|
//| AnimateDread |
|
||
|
|
//| https://www.mql5.com |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
#include "..\Variables\IndicatorTuneRanges.mqh"
|
||
|
|
//--- flat count of AutoTuneIndicators-tunable params across all 5 AD indicators, used to
|
||
|
|
//--- persist/restore the "winning" values in the .nnw file. ATR and Volume are intentionally NOT
|
||
|
|
//--- included: ATR's only tunable knob is m_periods, the shared bar lookback (ind_Periods);
|
||
|
|
//--- Volume's applied-price type (tick vs real) is kept as a plain manual input (VolumeData) since
|
||
|
|
//--- not every symbol has real volume available.
|
||
|
|
#define AD_TUNE_PARAM_COUNT 30
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Currently-active tunable input values for each AD indicator (AutoTuneIndicators search space).
|
||
|
|
//| InpContextMode/InpSessionType/InpSessionCount are session choices, not accuracy knobs, and are
|
||
|
|
//| hardcoded to the indicators' own defaults in CExpertSignalAIBase::InitAD*() rather than
|
||
|
|
//| stored/tuned here.
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
struct SADCumulativeDeltaParams
|
||
|
|
{
|
||
|
|
int lookback;
|
||
|
|
double volClimax, volHigh, rangeClimax, rangeSignificant, stVolRatio, atrMult;
|
||
|
|
};
|
||
|
|
struct SADShorteningOfThrustParams
|
||
|
|
{
|
||
|
|
int thrustLookback, minImpulses;
|
||
|
|
double sotThreshold;
|
||
|
|
};
|
||
|
|
struct SADWyckoffEventStreamParams
|
||
|
|
{
|
||
|
|
int lookback, zigzag;
|
||
|
|
double volClimax, volHigh, rangeClimax, rangeSignificant, stVolRatio, atr;
|
||
|
|
};
|
||
|
|
struct SADWyckoffFailedStructureParams
|
||
|
|
{
|
||
|
|
int lookback, zigzagStrength;
|
||
|
|
double volClimax, volHigh, rangeClimax, rangeSignificant, stVolRatio, atrMult;
|
||
|
|
};
|
||
|
|
struct SADWyckoffSignificantBarInversionParams
|
||
|
|
{
|
||
|
|
int lookback;
|
||
|
|
double rangeSignificant, volumeHigh, atr;
|
||
|
|
};
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Class CADIndicatorTuner. |
|
||
|
|
//| Owns the AutoTuneIndicators search-space state (current + best-known tunable values for all 5 |
|
||
|
|
//| AD indicators) and its own mutation logic (random perturbation, flatten/unflatten for .nnw |
|
||
|
|
//| persistence, win/loss bookkeeping) - extracted out of CExpertSignalAIBase (SOLID cleanup) since |
|
||
|
|
//| this state and behavior is entirely self-contained: it never touches Net, Train()'s state |
|
||
|
|
//| machine, or anything else in CExpertSignalAIBase. CExpertSignalAIBase::TuneIndicatorsAndTrain() |
|
||
|
|
//| (which DOES orchestrate Train()/Net/checkpointing around this tuner) stays put - that outer loop |
|
||
|
|
//| is exactly as tightly coupled to Train()'s resumable state machine as Train() itself, so it's |
|
||
|
|
//| deliberately NOT pulled in here; see this file's declaration comment in ExpertSignalAIBase.mqh |
|
||
|
|
//| for the full rationale. |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
class CADIndicatorTuner
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
SADCumulativeDeltaParams adCumDelta;
|
||
|
|
SADShorteningOfThrustParams adSOT;
|
||
|
|
SADWyckoffEventStreamParams adWES;
|
||
|
|
SADWyckoffFailedStructureParams adWFS;
|
||
|
|
SADWyckoffSignificantBarInversionParams adWSBI;
|
||
|
|
//--- best-known copies of the above, kept during TuneIndicatorsAndTrain() so a losing trial can
|
||
|
|
//--- restore rather than drift from a bad candidate - see SaveAsBest()/RestoreBest().
|
||
|
|
SADCumulativeDeltaParams bestAdCumDelta;
|
||
|
|
SADShorteningOfThrustParams bestAdSOT;
|
||
|
|
SADWyckoffEventStreamParams bestAdWES;
|
||
|
|
SADWyckoffFailedStructureParams bestAdWFS;
|
||
|
|
SADWyckoffSignificantBarInversionParams bestAdWSBI;
|
||
|
|
CADIndicatorTuner(void);
|
||
|
|
//--- flattens/restores the tunable param structs to/from a fixed-size array so they can be
|
||
|
|
//--- persisted alongside the network weights (see AI/Network.mqh Save()/Load())
|
||
|
|
void Flatten(double &arr[]);
|
||
|
|
void Unflatten(const double &arr[]);
|
||
|
|
//--- randomly perturbs one tunable param of one enabled AD indicator, within IndicatorTuneRanges.mqh
|
||
|
|
//--- bounds. useCumDelta/useSOT/useWES/useWFS/useWSBI mirror CExpertSignalAIBase's
|
||
|
|
//--- m_useADCumulativeDelta/etc. enable flags - no-op if all five are false.
|
||
|
|
void PerturbRandom(bool useCumDelta, bool useSOT, bool useWES, bool useWFS, bool useWSBI);
|
||
|
|
//--- snapshots current -> best (a winning trial) / restores best -> current (undoing a losing trial)
|
||
|
|
void SaveAsBest(void);
|
||
|
|
void RestoreBest(void);
|
||
|
|
};
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Defaults mirror each CustomIndicators\AD*.mq5 input's own default. |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
CADIndicatorTuner::CADIndicatorTuner(void)
|
||
|
|
{
|
||
|
|
adCumDelta.lookback = 50;
|
||
|
|
adCumDelta.volClimax = 2.5;
|
||
|
|
adCumDelta.volHigh = 1.5;
|
||
|
|
adCumDelta.rangeClimax = 1.8;
|
||
|
|
adCumDelta.rangeSignificant = 1.2;
|
||
|
|
adCumDelta.stVolRatio = 0.6;
|
||
|
|
adCumDelta.atrMult = 0.5;
|
||
|
|
adSOT.thrustLookback = 30;
|
||
|
|
adSOT.minImpulses = 3;
|
||
|
|
adSOT.sotThreshold = 0.30;
|
||
|
|
adWES.lookback = 50;
|
||
|
|
adWES.zigzag = 3;
|
||
|
|
adWES.volClimax = 2.5;
|
||
|
|
adWES.volHigh = 1.5;
|
||
|
|
adWES.rangeClimax = 1.8;
|
||
|
|
adWES.rangeSignificant = 1.2;
|
||
|
|
adWES.stVolRatio = 0.6;
|
||
|
|
adWES.atr = 0.5;
|
||
|
|
adWFS.lookback = 50;
|
||
|
|
adWFS.zigzagStrength = 3;
|
||
|
|
adWFS.volClimax = 2.5;
|
||
|
|
adWFS.volHigh = 1.5;
|
||
|
|
adWFS.rangeClimax = 1.8;
|
||
|
|
adWFS.rangeSignificant = 1.2;
|
||
|
|
adWFS.stVolRatio = 0.6;
|
||
|
|
adWFS.atrMult = 0.5;
|
||
|
|
adWSBI.lookback = 50;
|
||
|
|
adWSBI.rangeSignificant = 1.2;
|
||
|
|
adWSBI.volumeHigh = 1.5;
|
||
|
|
adWSBI.atr = 0.5;
|
||
|
|
SaveAsBest();
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void CADIndicatorTuner::Flatten(double &arr[])
|
||
|
|
{
|
||
|
|
ArrayResize(arr, AD_TUNE_PARAM_COUNT);
|
||
|
|
int i = 0;
|
||
|
|
arr[i++] = adCumDelta.lookback;
|
||
|
|
arr[i++] = adCumDelta.volClimax;
|
||
|
|
arr[i++] = adCumDelta.volHigh;
|
||
|
|
arr[i++] = adCumDelta.rangeClimax;
|
||
|
|
arr[i++] = adCumDelta.rangeSignificant;
|
||
|
|
arr[i++] = adCumDelta.stVolRatio;
|
||
|
|
arr[i++] = adCumDelta.atrMult;
|
||
|
|
arr[i++] = adSOT.thrustLookback;
|
||
|
|
arr[i++] = adSOT.minImpulses;
|
||
|
|
arr[i++] = adSOT.sotThreshold;
|
||
|
|
arr[i++] = adWES.lookback;
|
||
|
|
arr[i++] = adWES.zigzag;
|
||
|
|
arr[i++] = adWES.volClimax;
|
||
|
|
arr[i++] = adWES.volHigh;
|
||
|
|
arr[i++] = adWES.rangeClimax;
|
||
|
|
arr[i++] = adWES.rangeSignificant;
|
||
|
|
arr[i++] = adWES.stVolRatio;
|
||
|
|
arr[i++] = adWES.atr;
|
||
|
|
arr[i++] = adWFS.lookback;
|
||
|
|
arr[i++] = adWFS.zigzagStrength;
|
||
|
|
arr[i++] = adWFS.volClimax;
|
||
|
|
arr[i++] = adWFS.volHigh;
|
||
|
|
arr[i++] = adWFS.rangeClimax;
|
||
|
|
arr[i++] = adWFS.rangeSignificant;
|
||
|
|
arr[i++] = adWFS.stVolRatio;
|
||
|
|
arr[i++] = adWFS.atrMult;
|
||
|
|
arr[i++] = adWSBI.lookback;
|
||
|
|
arr[i++] = adWSBI.rangeSignificant;
|
||
|
|
arr[i++] = adWSBI.volumeHigh;
|
||
|
|
arr[i++] = adWSBI.atr;
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Reverse of Flatten(); ints are rounded on the way back in since |
|
||
|
|
//| everything is carried as double in the flat array. |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void CADIndicatorTuner::Unflatten(const double &arr[])
|
||
|
|
{
|
||
|
|
if(ArraySize(arr) != AD_TUNE_PARAM_COUNT)
|
||
|
|
return;
|
||
|
|
int i = 0;
|
||
|
|
adCumDelta.lookback = (int)MathRound(arr[i++]);
|
||
|
|
adCumDelta.volClimax = arr[i++];
|
||
|
|
adCumDelta.volHigh = arr[i++];
|
||
|
|
adCumDelta.rangeClimax = arr[i++];
|
||
|
|
adCumDelta.rangeSignificant = arr[i++];
|
||
|
|
adCumDelta.stVolRatio = arr[i++];
|
||
|
|
adCumDelta.atrMult = arr[i++];
|
||
|
|
adSOT.thrustLookback = (int)MathRound(arr[i++]);
|
||
|
|
adSOT.minImpulses = (int)MathRound(arr[i++]);
|
||
|
|
adSOT.sotThreshold = arr[i++];
|
||
|
|
adWES.lookback = (int)MathRound(arr[i++]);
|
||
|
|
adWES.zigzag = (int)MathRound(arr[i++]);
|
||
|
|
adWES.volClimax = arr[i++];
|
||
|
|
adWES.volHigh = arr[i++];
|
||
|
|
adWES.rangeClimax = arr[i++];
|
||
|
|
adWES.rangeSignificant = arr[i++];
|
||
|
|
adWES.stVolRatio = arr[i++];
|
||
|
|
adWES.atr = arr[i++];
|
||
|
|
adWFS.lookback = (int)MathRound(arr[i++]);
|
||
|
|
adWFS.zigzagStrength = (int)MathRound(arr[i++]);
|
||
|
|
adWFS.volClimax = arr[i++];
|
||
|
|
adWFS.volHigh = arr[i++];
|
||
|
|
adWFS.rangeClimax = arr[i++];
|
||
|
|
adWFS.rangeSignificant = arr[i++];
|
||
|
|
adWFS.stVolRatio = arr[i++];
|
||
|
|
adWFS.atrMult = arr[i++];
|
||
|
|
adWSBI.lookback = (int)MathRound(arr[i++]);
|
||
|
|
adWSBI.rangeSignificant = arr[i++];
|
||
|
|
adWSBI.volumeHigh = arr[i++];
|
||
|
|
adWSBI.atr = arr[i++];
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Randomly perturbs one tunable param of one randomly-chosen |
|
||
|
|
//| *enabled* AD indicator, within IndicatorTuneRanges.mqh bounds. |
|
||
|
|
//| No-op if no AD indicator is enabled. |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void CADIndicatorTuner::PerturbRandom(bool useCumDelta, bool useSOT, bool useWES, bool useWFS, bool useWSBI)
|
||
|
|
{
|
||
|
|
int enabled[5], n = 0;
|
||
|
|
if(useCumDelta)
|
||
|
|
enabled[n++] = 0;
|
||
|
|
if(useSOT)
|
||
|
|
enabled[n++] = 1;
|
||
|
|
if(useWES)
|
||
|
|
enabled[n++] = 2;
|
||
|
|
if(useWFS)
|
||
|
|
enabled[n++] = 3;
|
||
|
|
if(useWSBI)
|
||
|
|
enabled[n++] = 4;
|
||
|
|
if(n == 0)
|
||
|
|
return;
|
||
|
|
switch(enabled[MathRand() % n])
|
||
|
|
{
|
||
|
|
case 0:
|
||
|
|
{
|
||
|
|
switch(MathRand() % 7)
|
||
|
|
{
|
||
|
|
case 0:
|
||
|
|
adCumDelta.lookback = ADCUMDELTA_LOOKBACK_MIN + MathRand() % (ADCUMDELTA_LOOKBACK_MAX - ADCUMDELTA_LOOKBACK_MIN + 1);
|
||
|
|
break;
|
||
|
|
case 1:
|
||
|
|
adCumDelta.volClimax = ADCUMDELTA_VOLCLIMAX_MIN + (MathRand() / 32767.0) * (ADCUMDELTA_VOLCLIMAX_MAX - ADCUMDELTA_VOLCLIMAX_MIN);
|
||
|
|
break;
|
||
|
|
case 2:
|
||
|
|
adCumDelta.volHigh = ADCUMDELTA_VOLHIGH_MIN + (MathRand() / 32767.0) * (ADCUMDELTA_VOLHIGH_MAX - ADCUMDELTA_VOLHIGH_MIN);
|
||
|
|
break;
|
||
|
|
case 3:
|
||
|
|
adCumDelta.rangeClimax = ADCUMDELTA_RANGECLIMAX_MIN + (MathRand() / 32767.0) * (ADCUMDELTA_RANGECLIMAX_MAX - ADCUMDELTA_RANGECLIMAX_MIN);
|
||
|
|
break;
|
||
|
|
case 4:
|
||
|
|
adCumDelta.rangeSignificant = ADCUMDELTA_RANGESIGNIF_MIN + (MathRand() / 32767.0) * (ADCUMDELTA_RANGESIGNIF_MAX - ADCUMDELTA_RANGESIGNIF_MIN);
|
||
|
|
break;
|
||
|
|
case 5:
|
||
|
|
adCumDelta.stVolRatio = ADCUMDELTA_STVOLRATIO_MIN + (MathRand() / 32767.0) * (ADCUMDELTA_STVOLRATIO_MAX - ADCUMDELTA_STVOLRATIO_MIN);
|
||
|
|
break;
|
||
|
|
case 6:
|
||
|
|
adCumDelta.atrMult = ADCUMDELTA_ATRMULT_MIN + (MathRand() / 32767.0) * (ADCUMDELTA_ATRMULT_MAX - ADCUMDELTA_ATRMULT_MIN);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case 1:
|
||
|
|
{
|
||
|
|
switch(MathRand() % 3)
|
||
|
|
{
|
||
|
|
case 0:
|
||
|
|
adSOT.thrustLookback = ADSOT_LOOKBACK_MIN + MathRand() % (ADSOT_LOOKBACK_MAX - ADSOT_LOOKBACK_MIN + 1);
|
||
|
|
break;
|
||
|
|
case 1:
|
||
|
|
adSOT.minImpulses = ADSOT_MININPULSES_MIN + MathRand() % (ADSOT_MININPULSES_MAX - ADSOT_MININPULSES_MIN + 1);
|
||
|
|
break;
|
||
|
|
case 2:
|
||
|
|
adSOT.sotThreshold = ADSOT_THRESHOLD_MIN + (MathRand() / 32767.0) * (ADSOT_THRESHOLD_MAX - ADSOT_THRESHOLD_MIN);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case 2:
|
||
|
|
{
|
||
|
|
switch(MathRand() % 8)
|
||
|
|
{
|
||
|
|
case 0:
|
||
|
|
adWES.lookback = ADWES_LOOKBACK_MIN + MathRand() % (ADWES_LOOKBACK_MAX - ADWES_LOOKBACK_MIN + 1);
|
||
|
|
break;
|
||
|
|
case 1:
|
||
|
|
adWES.zigzag = ADWES_ZIGZAG_MIN + MathRand() % (ADWES_ZIGZAG_MAX - ADWES_ZIGZAG_MIN + 1);
|
||
|
|
break;
|
||
|
|
case 2:
|
||
|
|
adWES.volClimax = ADWES_VOLCLIMAX_MIN + (MathRand() / 32767.0) * (ADWES_VOLCLIMAX_MAX - ADWES_VOLCLIMAX_MIN);
|
||
|
|
break;
|
||
|
|
case 3:
|
||
|
|
adWES.volHigh = ADWES_VOLHIGH_MIN + (MathRand() / 32767.0) * (ADWES_VOLHIGH_MAX - ADWES_VOLHIGH_MIN);
|
||
|
|
break;
|
||
|
|
case 4:
|
||
|
|
adWES.rangeClimax = ADWES_RANGECLIMAX_MIN + (MathRand() / 32767.0) * (ADWES_RANGECLIMAX_MAX - ADWES_RANGECLIMAX_MIN);
|
||
|
|
break;
|
||
|
|
case 5:
|
||
|
|
adWES.rangeSignificant = ADWES_RANGESIGNIF_MIN + (MathRand() / 32767.0) * (ADWES_RANGESIGNIF_MAX - ADWES_RANGESIGNIF_MIN);
|
||
|
|
break;
|
||
|
|
case 6:
|
||
|
|
adWES.stVolRatio = ADWES_STVOLRATIO_MIN + (MathRand() / 32767.0) * (ADWES_STVOLRATIO_MAX - ADWES_STVOLRATIO_MIN);
|
||
|
|
break;
|
||
|
|
case 7:
|
||
|
|
adWES.atr = ADWES_ATR_MIN + (MathRand() / 32767.0) * (ADWES_ATR_MAX - ADWES_ATR_MIN);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case 3:
|
||
|
|
{
|
||
|
|
switch(MathRand() % 8)
|
||
|
|
{
|
||
|
|
case 0:
|
||
|
|
adWFS.lookback = ADWFS_LOOKBACK_MIN + MathRand() % (ADWFS_LOOKBACK_MAX - ADWFS_LOOKBACK_MIN + 1);
|
||
|
|
break;
|
||
|
|
case 1:
|
||
|
|
adWFS.zigzagStrength = ADWFS_ZIGZAGSTRENGTH_MIN + MathRand() % (ADWFS_ZIGZAGSTRENGTH_MAX - ADWFS_ZIGZAGSTRENGTH_MIN + 1);
|
||
|
|
break;
|
||
|
|
case 2:
|
||
|
|
adWFS.volClimax = ADWFS_VOLCLIMAX_MIN + (MathRand() / 32767.0) * (ADWFS_VOLCLIMAX_MAX - ADWFS_VOLCLIMAX_MIN);
|
||
|
|
break;
|
||
|
|
case 3:
|
||
|
|
adWFS.volHigh = ADWFS_VOLHIGH_MIN + (MathRand() / 32767.0) * (ADWFS_VOLHIGH_MAX - ADWFS_VOLHIGH_MIN);
|
||
|
|
break;
|
||
|
|
case 4:
|
||
|
|
adWFS.rangeClimax = ADWFS_RANGECLIMAX_MIN + (MathRand() / 32767.0) * (ADWFS_RANGECLIMAX_MAX - ADWFS_RANGECLIMAX_MIN);
|
||
|
|
break;
|
||
|
|
case 5:
|
||
|
|
adWFS.rangeSignificant = ADWFS_RANGESIGNIF_MIN + (MathRand() / 32767.0) * (ADWFS_RANGESIGNIF_MAX - ADWFS_RANGESIGNIF_MIN);
|
||
|
|
break;
|
||
|
|
case 6:
|
||
|
|
adWFS.stVolRatio = ADWFS_STVOLRATIO_MIN + (MathRand() / 32767.0) * (ADWFS_STVOLRATIO_MAX - ADWFS_STVOLRATIO_MIN);
|
||
|
|
break;
|
||
|
|
case 7:
|
||
|
|
adWFS.atrMult = ADWFS_ATRMULT_MIN + (MathRand() / 32767.0) * (ADWFS_ATRMULT_MAX - ADWFS_ATRMULT_MIN);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case 4:
|
||
|
|
{
|
||
|
|
switch(MathRand() % 4)
|
||
|
|
{
|
||
|
|
case 0:
|
||
|
|
adWSBI.lookback = ADWSBI_LOOKBACK_MIN + MathRand() % (ADWSBI_LOOKBACK_MAX - ADWSBI_LOOKBACK_MIN + 1);
|
||
|
|
break;
|
||
|
|
case 1:
|
||
|
|
adWSBI.rangeSignificant = ADWSBI_RANGESIGNIF_MIN + (MathRand() / 32767.0) * (ADWSBI_RANGESIGNIF_MAX - ADWSBI_RANGESIGNIF_MIN);
|
||
|
|
break;
|
||
|
|
case 2:
|
||
|
|
adWSBI.volumeHigh = ADWSBI_VOLHIGH_MIN + (MathRand() / 32767.0) * (ADWSBI_VOLHIGH_MAX - ADWSBI_VOLHIGH_MIN);
|
||
|
|
break;
|
||
|
|
case 3:
|
||
|
|
adWSBI.atr = ADWSBI_ATR_MIN + (MathRand() / 32767.0) * (ADWSBI_ATR_MAX - ADWSBI_ATR_MIN);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void CADIndicatorTuner::SaveAsBest(void)
|
||
|
|
{
|
||
|
|
bestAdCumDelta = adCumDelta;
|
||
|
|
bestAdSOT = adSOT;
|
||
|
|
bestAdWES = adWES;
|
||
|
|
bestAdWFS = adWFS;
|
||
|
|
bestAdWSBI = adWSBI;
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void CADIndicatorTuner::RestoreBest(void)
|
||
|
|
{
|
||
|
|
adCumDelta = bestAdCumDelta;
|
||
|
|
adSOT = bestAdSOT;
|
||
|
|
adWES = bestAdWES;
|
||
|
|
adWFS = bestAdWFS;
|
||
|
|
adWSBI = bestAdWSBI;
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|