//+------------------------------------------------------------------+ //| Midas 6 Anchored VWAP.mq5 | //| Translated from Pine Script | //+------------------------------------------------------------------+ #property copyright "Translated from Pine Script" #property link "https://www.tradingview.com/script/tZMg8BFt/" #property version "1.03" // Added Interactive Draggable Anchors #property indicator_chart_window #property indicator_buffers 18 #property indicator_plots 6 //--- plot #1 #property indicator_label1 "#1 AVWAP" #property indicator_type1 DRAW_ARROW #property indicator_color1 clrLimeGreen #property indicator_width1 2 //--- plot #2 #property indicator_label2 "#2 AVWAP" #property indicator_type2 DRAW_ARROW #property indicator_color2 clrRed #property indicator_width2 2 //--- plot #3 #property indicator_label3 "#3 AVWAP" #property indicator_type3 DRAW_ARROW #property indicator_color3 clrNavy #property indicator_width3 2 //--- plot #4 #property indicator_label4 "#4 AVWAP" #property indicator_type4 DRAW_ARROW #property indicator_color4 clrPurple #property indicator_width4 2 //--- plot #5 #property indicator_label5 "#5 AVWAP" #property indicator_type5 DRAW_ARROW #property indicator_color5 clrTeal #property indicator_width5 2 //--- plot #6 #property indicator_label6 "#6 AVWAP" #property indicator_type6 DRAW_ARROW #property indicator_color6 clrGray #property indicator_width6 2 //--- Enums enum ENUM_SOURCE { SRC_CLOSE, // Close SRC_HL2, // HL/2 SRC_HLC3, // HLC/3 SRC_OHLC4 // OHLC/4 }; enum ENUM_VOL_TYPE { VOL_TICK, // Tick Volume VOL_REAL // Real Volume }; //--- Inputs input bool InpInteractive = true; // Use Interactive Draggable Anchors input bool InpEnable1 = true; // #1 Enable input datetime InpDate1 = D'2020.01.01 00:00:00'; // #1 Start Time input ENUM_SOURCE InpSrc1 = SRC_HLC3; // #1 Source input bool InpEnable2 = false; // #2 Enable input datetime InpDate2 = D'2020.02.01 00:00:00'; // #2 Start Time input ENUM_SOURCE InpSrc2 = SRC_HLC3; // #2 Source input bool InpEnable3 = false; // #3 Enable input datetime InpDate3 = D'2020.03.01 00:00:00'; // #3 Start Time input ENUM_SOURCE InpSrc3 = SRC_HLC3; // #3 Source input bool InpEnable4 = false; // #4 Enable input datetime InpDate4 = D'2020.04.01 00:00:00'; // #4 Start Time input ENUM_SOURCE InpSrc4 = SRC_HLC3; // #4 Source input bool InpEnable5 = false; // #5 Enable input datetime InpDate5 = D'2020.05.01 00:00:00'; // #5 Start Time input ENUM_SOURCE InpSrc5 = SRC_HLC3; // #5 Source input bool InpEnable6 = false; // #6 Enable input datetime InpDate6 = D'2020.06.01 00:00:00'; // #6 Start Time input ENUM_SOURCE InpSrc6 = SRC_HLC3; // #6 Source input color InpLbText = clrWhite; // Label text color input color InpLbBg = clrNavy; // Label background (Text used instead) input ENUM_VOL_TYPE InpVolType = VOL_TICK; // Volume Type to use //--- Indicator buffers double BufferVWAP1[]; double BufferVWAP2[]; double BufferVWAP3[]; double BufferVWAP4[]; double BufferVWAP5[]; double BufferVWAP6[]; double BufferCumVol1[]; double BufferCumVol2[]; double BufferCumVol3[]; double BufferCumVol4[]; double BufferCumVol5[]; double BufferCumVol6[]; double BufferCumVolPrice1[]; double BufferCumVolPrice2[]; double BufferCumVolPrice3[]; double BufferCumVolPrice4[]; double BufferCumVolPrice5[]; double BufferCumVolPrice6[]; //--- Global variables bool g_enabled[6]; datetime g_date[6]; ENUM_SOURCE g_src[6]; color g_colors[6] = {clrLimeGreen, clrRed, clrNavy, clrPurple, clrTeal, clrGray}; string g_prefix = "MidasVWAP_Label_"; bool g_need_recalc = false; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- bind arrays to indicator buffers SetIndexBuffer(0, BufferVWAP1, INDICATOR_DATA); PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0); SetIndexBuffer(1, BufferVWAP2, INDICATOR_DATA); PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0.0); SetIndexBuffer(2, BufferVWAP3, INDICATOR_DATA); PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, 0.0); SetIndexBuffer(3, BufferVWAP4, INDICATOR_DATA); PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, 0.0); SetIndexBuffer(4, BufferVWAP5, INDICATOR_DATA); PlotIndexSetDouble(4, PLOT_EMPTY_VALUE, 0.0); SetIndexBuffer(5, BufferVWAP6, INDICATOR_DATA); PlotIndexSetDouble(5, PLOT_EMPTY_VALUE, 0.0); // Apply PineScript match (plot.style_circles = 159 Dot Character) for(int p=0; p<6; p++) PlotIndexSetInteger(p, PLOT_ARROW, 159); // Hidden Custom Buffers for CumVol and CumVolPrice SetIndexBuffer(6, BufferCumVol1, INDICATOR_CALCULATIONS); SetIndexBuffer(7, BufferCumVolPrice1, INDICATOR_CALCULATIONS); SetIndexBuffer(8, BufferCumVol2, INDICATOR_CALCULATIONS); SetIndexBuffer(9, BufferCumVolPrice2, INDICATOR_CALCULATIONS); SetIndexBuffer(10, BufferCumVol3, INDICATOR_CALCULATIONS); SetIndexBuffer(11, BufferCumVolPrice3, INDICATOR_CALCULATIONS); SetIndexBuffer(12, BufferCumVol4, INDICATOR_CALCULATIONS); SetIndexBuffer(13, BufferCumVolPrice4, INDICATOR_CALCULATIONS); SetIndexBuffer(14, BufferCumVol5, INDICATOR_CALCULATIONS); SetIndexBuffer(15, BufferCumVolPrice5, INDICATOR_CALCULATIONS); SetIndexBuffer(16, BufferCumVol6, INDICATOR_CALCULATIONS); SetIndexBuffer(17, BufferCumVolPrice6, INDICATOR_CALCULATIONS); //--- initialize arrays g_enabled[0] = InpEnable1; g_date[0] = InpDate1; g_src[0] = InpSrc1; g_enabled[1] = InpEnable2; g_date[1] = InpDate2; g_src[1] = InpSrc2; g_enabled[2] = InpEnable3; g_date[2] = InpDate3; g_src[2] = InpSrc3; g_enabled[3] = InpEnable4; g_date[3] = InpDate4; g_src[3] = InpSrc4; g_enabled[4] = InpEnable5; g_date[4] = InpDate5; g_src[4] = InpSrc5; g_enabled[5] = InpEnable6; g_date[5] = InpDate6; g_src[5] = InpSrc6; // Setup Interactive Anchor Lines if (InpInteractive) { for(int v=0; v<6; v++) { string name = "MidasVWAP_Anchor_" + IntegerToString(v+1); if(g_enabled[v]) { if(ObjectFind(0, name) >= 0) { // Object exists, inherit its dragged time to persist user changes during timeframe switches g_date[v] = (datetime)ObjectGetInteger(0, name, OBJPROP_TIME); } else { // Create object ObjectCreate(0, name, OBJ_VLINE, 0, g_date[v], 0); ObjectSetInteger(0, name, OBJPROP_COLOR, g_colors[v]); ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_DOT); ObjectSetInteger(0, name, OBJPROP_WIDTH, 1); ObjectSetInteger(0, name, OBJPROP_SELECTABLE, true); ObjectSetInteger(0, name, OBJPROP_SELECTED, false); ObjectSetInteger(0, name, OBJPROP_HIDDEN, true); ObjectSetString(0, name, OBJPROP_TOOLTIP, "Double-Click to select, then Drag to move Anchor #" + IntegerToString(v+1) + " Date"); } } else { ObjectDelete(0, name); } } } IndicatorSetInteger(INDICATOR_DIGITS, _Digits); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- remove all label objects when indicator is removed ObjectsDeleteAll(0, g_prefix); // Only delete anchor lines if indicator is completely purged from chart // (Allows anchors to survive changing timeframes) if(reason != REASON_CHARTCHANGE) { ObjectsDeleteAll(0, "MidasVWAP_Anchor_"); } } //+------------------------------------------------------------------+ //| Helper to calculate typical price based on source | //+------------------------------------------------------------------+ double GetPrice(ENUM_SOURCE src, double o, double h, double l, double c) { switch(src) { case SRC_CLOSE: return c; case SRC_HL2: return (h + l) / 2.0; case SRC_HLC3: return (h + l + c) / 3.0; case SRC_OHLC4: return (o + h + l + c) / 4.0; } return c; } //+------------------------------------------------------------------+ //| Helper to calculate step logic for VWAP | //+------------------------------------------------------------------+ void CalculateVWAP(int v, int i, int rates_total, int prev_calculated, double price, double vol, datetime t, datetime t_prev, const double &high[], const double &low[], const double &close[], const datetime &time[], double &bufVWAP[], double &bufCumVol[], double &bufCumVolPrice[]) { if(!g_enabled[v]) { bufVWAP[i] = 0.0; bufCumVol[i] = 0.0; bufCumVolPrice[i] = 0.0; return; } if(t >= g_date[v]) { double current_volprice = price * vol; // First bar that crosses the anchor time threshold if(t_prev < g_date[v]) { bufCumVol[i] = vol; bufCumVolPrice[i] = current_volprice; bufVWAP[i] = price; // Create dynamic text label exactly at the anchor starting bar if(i == rates_total - 1 || prev_calculated == 0) { string obj_name = g_prefix + IntegerToString(v+1); if(ObjectFind(0, obj_name) < 0) { double offset = (high[i] - low[i]) * 0.5; if(offset == 0) offset = close[i] * 0.001; ObjectCreate(0, obj_name, OBJ_TEXT, 0, time[i], high[i] + offset); ObjectSetString(0, obj_name, OBJPROP_TEXT, "▼ [" + IntegerToString(v+1) + "]"); ObjectSetInteger(0, obj_name, OBJPROP_COLOR, InpLbText); ObjectSetString(0, obj_name, OBJPROP_FONT, "Arial"); ObjectSetInteger(0, obj_name, OBJPROP_FONTSIZE, 10); ObjectSetInteger(0, obj_name, OBJPROP_ANCHOR, ANCHOR_LOWER); // Tooltips ObjectSetString(0, obj_name, OBJPROP_TOOLTIP, "Anchored VWAP #" + IntegerToString(v+1) + " Start"); } } } else { // Subsequent ongoing calculation bars double prev_cumvol = (i > 0) ? bufCumVol[i-1] : 0.0; double prev_cumvolprice = (i > 0) ? bufCumVolPrice[i-1] : 0.0; bufCumVol[i] = prev_cumvol + vol; bufCumVolPrice[i] = prev_cumvolprice + current_volprice; if(bufCumVol[i] != 0.0) bufVWAP[i] = bufCumVolPrice[i] / bufCumVol[i]; else bufVWAP[i] = (i > 0) ? bufVWAP[i-1] : price; } } else { // Reset for data historically preceding activation date bufVWAP[i] = 0.0; bufCumVol[i] = 0.0; bufCumVolPrice[i] = 0.0; } } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ 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 < 1) return(0); int start = (prev_calculated > 0) ? prev_calculated - 1 : 0; //--- Detect if Visual Anchors have been Dragged dynamically if(InpInteractive) { for(int v=0; v<6; v++) { if(g_enabled[v]) { string name = "MidasVWAP_Anchor_" + IntegerToString(v+1); if(ObjectFind(0, name) >= 0) { datetime obj_date = (datetime)ObjectGetInteger(0, name, OBJPROP_TIME); if(obj_date != g_date[v]) { g_date[v] = obj_date; // Update memory to drifted line g_need_recalc = true; // Signal full array wipe overwrite } } } } } //--- Trigger Full Recalculation Override upon Drop if(g_need_recalc) { start = 0; // Force arrays to iterate and rewrite from index 0 ObjectsDeleteAll(0, g_prefix); // Safely wipe old arrow labels so they jump to new anchors g_need_recalc = false; } //--- Main Execution Loop for(int i = start; i < rates_total; i++) { double vol = (InpVolType == VOL_TICK) ? (double)tick_volume[i] : (double)volume[i]; if(vol == 0) vol = 1; // Fallback to unweighted MA if no volume is provided at all datetime t = time[i]; datetime t_prev = (i > 0) ? time[i-1] : 0; double p1 = GetPrice(g_src[0], open[i], high[i], low[i], close[i]); CalculateVWAP(0, i, rates_total, prev_calculated, p1, vol, t, t_prev, high, low, close, time, BufferVWAP1, BufferCumVol1, BufferCumVolPrice1); double p2 = GetPrice(g_src[1], open[i], high[i], low[i], close[i]); CalculateVWAP(1, i, rates_total, prev_calculated, p2, vol, t, t_prev, high, low, close, time, BufferVWAP2, BufferCumVol2, BufferCumVolPrice2); double p3 = GetPrice(g_src[2], open[i], high[i], low[i], close[i]); CalculateVWAP(2, i, rates_total, prev_calculated, p3, vol, t, t_prev, high, low, close, time, BufferVWAP3, BufferCumVol3, BufferCumVolPrice3); double p4 = GetPrice(g_src[3], open[i], high[i], low[i], close[i]); CalculateVWAP(3, i, rates_total, prev_calculated, p4, vol, t, t_prev, high, low, close, time, BufferVWAP4, BufferCumVol4, BufferCumVolPrice4); double p5 = GetPrice(g_src[4], open[i], high[i], low[i], close[i]); CalculateVWAP(4, i, rates_total, prev_calculated, p5, vol, t, t_prev, high, low, close, time, BufferVWAP5, BufferCumVol5, BufferCumVolPrice5); double p6 = GetPrice(g_src[5], open[i], high[i], low[i], close[i]); CalculateVWAP(5, i, rates_total, prev_calculated, p6, vol, t, t_prev, high, low, close, time, BufferVWAP6, BufferCumVol6, BufferCumVolPrice6); } return(rates_total); } //+------------------------------------------------------------------+