mql5/RollingVWAP.mq5

155 lines
6.1 KiB
MQL5
Raw Permalink Normal View History

2026-05-08 10:57:33 +00:00
//+------------------------------------------------------------------+
//| RollingVWAP.mq5 |
//| VWAP Dynamique - FIFO O(1) + Écart-Type + Coloration Ternaire |
//+------------------------------------------------------------------+
#property copyright "t00nster"
#property link "https://heretik666.free.fr/brousoufs"
#property version "3.00"
#property indicator_chart_window
#property indicator_buffers 9 // 3 Data + 1 Color + 5 Calculs
#property indicator_plots 3
// --- Apparence visuelle (DRAW_COLOR_LINE) ---
#property indicator_label1 "Rolling VWAP"
#property indicator_type1 DRAW_COLOR_LINE
// Index des couleurs : 0 = Vert (Hausse), 1 = Rouge (Baisse), 2 = Bleu (Neutre)
#property indicator_color1 clrLime,clrRed,clrDodgerBlue
#property indicator_style1 STYLE_SOLID
#property indicator_width1 2
//--- Plot Upper Band (+2.0 SD)
#property indicator_label2 "Rolling VWAP Upper"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrGray
#property indicator_style2 STYLE_DASH
//--- Plot Lower Band (-2.0 SD)
#property indicator_label3 "Rolling VWAP Lower"
#property indicator_type3 DRAW_LINE
#property indicator_color3 clrGray
#property indicator_style3 STYLE_DASH
// --- Paramètres ---
input int InpVWAPPeriod = 15; // Taille du Buffer LIFO/FIFO
input double InpTolerance = 0.05; // Tolérance au bruit (Delta)
// --- Buffers d'affichage ---
double VWAPBuffer[];
2026-05-08 11:00:08 +00:00
int VWAPColorBuffer[]; // Buffer qui stocke l'état (0, 1 ou 2)
2026-05-08 10:57:33 +00:00
double BufferUpper[];
double BufferLower[];
// --- Buffers de calcul (Invisibles) ---
double StdDevBuffer[]; // Index 4 (Lu par l'EA)
double SumPVBuffer[]; // Index 5
double SumVBuffer[]; // Index 4
double SumPBuffer[]; // Index 5
double SumP2Buffer[]; // Index 6
//+------------------------------------------------------------------+
int OnInit() {
// Buffers visibles
SetIndexBuffer(0, VWAPBuffer, INDICATOR_DATA);
SetIndexBuffer(1, VWAPColorBuffer, INDICATOR_COLOR_INDEX);
SetIndexBuffer(2, BufferUpper, INDICATOR_DATA);
SetIndexBuffer(3, BufferLower, INDICATOR_DATA);
// Buffers de calcul
SetIndexBuffer(4, StdDevBuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer(5, SumPVBuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer(6, SumVBuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer(7, SumPBuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer(8, SumP2Buffer, INDICATOR_CALCULATIONS);
IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
IndicatorSetString(INDICATOR_SHORTNAME, "RVWAP(" + IntegerToString(InpVWAPPeriod) + ")");
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[]) {
if(rates_total < InpVWAPPeriod) return 0;
int limit = prev_calculated == 0 ? InpVWAPPeriod : prev_calculated - 1;
// --- INITIALISATION DE LA TOUTE PREMIÈRE FENÊTRE ---
if(prev_calculated == 0) {
double s_pv = 0, s_v = 0, s_p = 0, s_p2 = 0;
for(int j = 0; j < InpVWAPPeriod; j++) {
double typ = (high[j] + low[j] + close[j]) / 3.0;
double vol = (double)tick_volume[j];
s_pv += typ * vol;
s_v += vol;
s_p += typ;
s_p2 += typ * typ;
}
int init_idx = InpVWAPPeriod - 1;
SumPVBuffer[init_idx] = s_pv;
SumVBuffer[init_idx] = s_v;
SumPBuffer[init_idx] = s_p;
SumP2Buffer[init_idx] = s_p2;
VWAPBuffer[init_idx] = (s_v > 0) ? NormalizeDouble((s_pv / s_v), _Digits) : NormalizeDouble(close[init_idx], _Digits);
VWAPColorBuffer[init_idx] = 2.0; // État initial = Neutre
double vwap = VWAPBuffer[init_idx];
double var = (s_p2 / InpVWAPPeriod) - 2 * vwap * (s_p / InpVWAPPeriod) + (vwap * vwap);
StdDevBuffer[init_idx] = MathSqrt(MathMax(0.0, var));
BufferUpper[init_idx] = NormalizeDouble(vwap + (1.618 * StdDevBuffer[init_idx]), _Digits);
BufferLower[init_idx] = NormalizeDouble(vwap - (1.618 * StdDevBuffer[init_idx]), _Digits);
}
// --- LE MOTEUR FIFO O(1) & LOGIQUE TERNAIRE ---
for(int i = limit; i < rates_total; i++) {
if (i < InpVWAPPeriod) continue;
double head_typ = (high[i] + low[i] + close[i]) / 3.0;
double head_vol = (double)tick_volume[i];
int tail_idx = i - InpVWAPPeriod;
double tail_typ = (high[tail_idx] + low[tail_idx] + close[tail_idx]) / 3.0;
double tail_vol = (double)tick_volume[tail_idx];
// Mise à jour de la mémoire FIFO
SumPVBuffer[i] = NormalizeDouble(SumPVBuffer[i - 1] + (head_typ * head_vol) - (tail_typ * tail_vol), _Digits);
SumVBuffer[i] = NormalizeDouble(SumVBuffer[i - 1] + head_vol - tail_vol, _Digits);
SumPBuffer[i] = NormalizeDouble(SumPBuffer[i - 1] + head_typ - tail_typ, _Digits);
SumP2Buffer[i] = NormalizeDouble(SumP2Buffer[i - 1] + (head_typ * head_typ) - (tail_typ * tail_typ), _Digits);
// Calcul VWAP
VWAPBuffer[i] = NormalizeDouble((SumVBuffer[i] > 0) ? (SumPVBuffer[i] / SumVBuffer[i]) : close[i], _Digits);
// --- ARCHITECTURE TERNAIRE (Coloration de la pente) ---
double delta = VWAPBuffer[i] - VWAPBuffer[i - 1];
if(delta > InpTolerance)
2026-05-08 11:00:08 +00:00
VWAPColorBuffer[i] = 0; // Pente haussière franche (Vert)
2026-05-08 10:57:33 +00:00
else if(delta < -InpTolerance)
2026-05-08 11:00:08 +00:00
VWAPColorBuffer[i] = 1; // Pente baissière franche (Rouge)
2026-05-08 10:57:33 +00:00
else
2026-05-08 11:00:08 +00:00
VWAPColorBuffer[i] = 2; // Stagnation, bruit absorbé (Bleu)
2026-05-08 10:57:33 +00:00
// Calcul Écart-Type
double vwap = VWAPBuffer[i];
double var = (SumP2Buffer[i] / InpVWAPPeriod) - 2 * vwap * (SumPBuffer[i] / InpVWAPPeriod) + (vwap * vwap);
StdDevBuffer[i] = NormalizeDouble(MathSqrt(MathMax(0.0, var)), _Digits);
BufferUpper[i] = NormalizeDouble(vwap + (1.618 * StdDevBuffer[i]), _Digits);
BufferLower[i] = NormalizeDouble(vwap - (1.618 * StdDevBuffer[i]), _Digits);
}
return rates_total;
2026-05-08 10:49:27 +00:00
}