mirror of
https://github.com/softwaredevelop/mql5.git
synced 2026-08-20 15:58:07 +00:00
feat: Outputs State Buffer
This commit is contained in:
@@ -3,20 +3,21 @@
|
|||||||
//| Copyright 2026, xxxxxxxx|
|
//| Copyright 2026, xxxxxxxx|
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
#property copyright "Copyright 2026, xxxxxxxx"
|
#property copyright "Copyright 2026, xxxxxxxx"
|
||||||
#property version "1.00"
|
#property version "1.10"
|
||||||
#property description "Institutional Absorption Detector (Wyckoff)."
|
#property description "Institutional Absorption Detector."
|
||||||
#property description "Draws Supply/Demand zones based on Volume/Price anomalies."
|
#property description "Draws Supply/Demand zones & Outputs State Buffer."
|
||||||
|
|
||||||
#property indicator_chart_window
|
#property indicator_chart_window
|
||||||
#property indicator_buffers 4
|
#property indicator_buffers 5
|
||||||
#property indicator_plots 2
|
#property indicator_plots 2
|
||||||
|
|
||||||
// Use arrow buffers just to mark the signal bar visually on top/bottom
|
// Plot 1: Bull Arrow
|
||||||
#property indicator_label1 "Bull Abs"
|
#property indicator_label1 "Bull Abs"
|
||||||
#property indicator_type1 DRAW_ARROW
|
#property indicator_type1 DRAW_ARROW
|
||||||
#property indicator_color1 clrLime
|
#property indicator_color1 clrLime
|
||||||
#property indicator_width1 2
|
#property indicator_width1 2
|
||||||
|
|
||||||
|
// Plot 2: Bear Arrow
|
||||||
#property indicator_label2 "Bear Abs"
|
#property indicator_label2 "Bear Abs"
|
||||||
#property indicator_type2 DRAW_ARROW
|
#property indicator_type2 DRAW_ARROW
|
||||||
#property indicator_color2 clrRed
|
#property indicator_color2 clrRed
|
||||||
@@ -26,22 +27,22 @@
|
|||||||
#include <MyIncludes\RelativeVolume_Calculator.mqh>
|
#include <MyIncludes\RelativeVolume_Calculator.mqh>
|
||||||
|
|
||||||
//--- Parameters
|
//--- Parameters
|
||||||
input int InpATRPeriod = 14; // Volatility Period
|
input int InpATRPeriod = 14;
|
||||||
input int InpRVOLPeriod = 20; // Volume Period
|
input int InpRVOLPeriod = 20;
|
||||||
input int InpHistoryBars = 500; // Max Bars to analyze (for objects)
|
input int InpHistoryBars = 500; // Limit object creation history
|
||||||
|
|
||||||
//--- Buffers
|
//--- Buffers
|
||||||
double BufBull[];
|
double BufBull[];
|
||||||
double BufBear[];
|
double BufBear[];
|
||||||
double BufATR[]; // Internal
|
double BufATR[];
|
||||||
double BufRVOL[]; // Internal
|
double BufRVOL[];
|
||||||
|
double BufState[]; // 0=None, 1=Bull, -1=Bear, 2=Climax, 0.5=Neut
|
||||||
|
|
||||||
//--- Objects
|
|
||||||
CATRCalculator *g_atr;
|
CATRCalculator *g_atr;
|
||||||
CRelativeVolumeCalculator *g_rvol;
|
CRelativeVolumeCalculator *g_rvol;
|
||||||
|
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
//| Init |
|
//| |
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
int OnInit()
|
int OnInit()
|
||||||
{
|
{
|
||||||
@@ -49,17 +50,15 @@ int OnInit()
|
|||||||
SetIndexBuffer(1, BufBear, INDICATOR_DATA);
|
SetIndexBuffer(1, BufBear, INDICATOR_DATA);
|
||||||
SetIndexBuffer(2, BufATR, INDICATOR_CALCULATIONS);
|
SetIndexBuffer(2, BufATR, INDICATOR_CALCULATIONS);
|
||||||
SetIndexBuffer(3, BufRVOL, INDICATOR_CALCULATIONS);
|
SetIndexBuffer(3, BufRVOL, INDICATOR_CALCULATIONS);
|
||||||
|
SetIndexBuffer(4, BufState, INDICATOR_CALCULATIONS);
|
||||||
|
|
||||||
PlotIndexSetInteger(0, PLOT_ARROW, 233); // Up Arrow
|
PlotIndexSetInteger(0, PLOT_ARROW, 233);
|
||||||
PlotIndexSetInteger(1, PLOT_ARROW, 234); // Down Arrow
|
PlotIndexSetInteger(1, PLOT_ARROW, 234);
|
||||||
|
|
||||||
g_atr = new CATRCalculator();
|
g_atr = new CATRCalculator();
|
||||||
if(!g_atr.Init(InpATRPeriod, ATR_POINTS))
|
g_atr.Init(InpATRPeriod, ATR_POINTS);
|
||||||
return INIT_FAILED;
|
|
||||||
|
|
||||||
g_rvol = new CRelativeVolumeCalculator();
|
g_rvol = new CRelativeVolumeCalculator();
|
||||||
if(!g_rvol.Init(InpRVOLPeriod))
|
g_rvol.Init(InpRVOLPeriod);
|
||||||
return INIT_FAILED;
|
|
||||||
|
|
||||||
IndicatorSetString(INDICATOR_SHORTNAME, "Absorption Pro");
|
IndicatorSetString(INDICATOR_SHORTNAME, "Absorption Pro");
|
||||||
return(INIT_SUCCEEDED);
|
return(INIT_SUCCEEDED);
|
||||||
@@ -78,47 +77,35 @@ void OnDeinit(const int r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
//| Calculate |
|
//| |
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
int OnCalculate(const int rates_total,
|
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[])
|
||||||
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[])
|
|
||||||
{
|
{
|
||||||
// Safety
|
|
||||||
if(rates_total < InpATRPeriod + InpRVOLPeriod)
|
if(rates_total < InpATRPeriod + InpRVOLPeriod)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// 1. Data Prep & Calc
|
|
||||||
g_atr.Calculate(rates_total, prev_calculated, open, high, low, close, BufATR);
|
g_atr.Calculate(rates_total, prev_calculated, open, high, low, close, BufATR);
|
||||||
g_rvol.Calculate(rates_total, prev_calculated, tick_volume, BufRVOL);
|
g_rvol.Calculate(rates_total, prev_calculated, tick_volume, BufRVOL);
|
||||||
|
|
||||||
// Limit loop for objects (don't draw 100000 objects)
|
int start = (prev_calculated > 0) ? prev_calculated - 1 : InpATRPeriod + InpRVOLPeriod;
|
||||||
// Always recalc recent history to update "Open" zones
|
|
||||||
int start = rates_total - InpHistoryBars;
|
|
||||||
if(start < 0)
|
|
||||||
start = 0;
|
|
||||||
|
|
||||||
// Optimization: Only create objects if not exists. But update "End Time" of active zones.
|
// Limit Drawing loop to history bars to avoid lag on recompiles with huge history
|
||||||
// Simplified approach: scan history, manage objects.
|
int draw_limit = rates_total - InpHistoryBars;
|
||||||
|
if(draw_limit < 0)
|
||||||
|
draw_limit = 0;
|
||||||
|
if(start < draw_limit)
|
||||||
|
start = draw_limit;
|
||||||
|
|
||||||
for(int i = start; i < rates_total; i++)
|
for(int i = start; i < rates_total; i++)
|
||||||
{
|
{
|
||||||
// Reset arrow buffers
|
|
||||||
BufBull[i] = EMPTY_VALUE;
|
BufBull[i] = EMPTY_VALUE;
|
||||||
BufBear[i] = EMPTY_VALUE;
|
BufBear[i] = EMPTY_VALUE;
|
||||||
|
BufState[i] = 0;
|
||||||
|
|
||||||
double atr = BufATR[i];
|
double atr = BufATR[i];
|
||||||
if(atr == 0)
|
if(atr == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// LOGIC from Script
|
|
||||||
double body = MathAbs(close[i] - open[i]);
|
double body = MathAbs(close[i] - open[i]);
|
||||||
double total_range = high[i] - low[i];
|
double total_range = high[i] - low[i];
|
||||||
double rvol = BufRVOL[i];
|
double rvol = BufRVOL[i];
|
||||||
@@ -137,70 +124,70 @@ int OnCalculate(const int rates_total,
|
|||||||
close_pos = (close[i] - low[i]) / total_range;
|
close_pos = (close[i] - low[i]) / total_range;
|
||||||
|
|
||||||
if(close_pos > 0.66)
|
if(close_pos > 0.66)
|
||||||
|
{
|
||||||
|
BufState[i] = 1.0;
|
||||||
is_bull = true;
|
is_bull = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
if(close_pos < 0.33)
|
if(close_pos < 0.33)
|
||||||
|
{
|
||||||
|
BufState[i] = -1.0;
|
||||||
is_bear = true;
|
is_bear = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Neutral Abs - maybe mark as yellow?
|
BufState[i] = 0.5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if(rvol > 3.5 && body < (0.6 * atr))
|
if(rvol > 3.5 && body < (0.6 * atr))
|
||||||
{
|
{
|
||||||
is_climax = true; // Use neutral/warning color
|
BufState[i] = 2.0;
|
||||||
|
is_climax = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drawing Logic
|
// Visuals & Objects
|
||||||
if(is_bull || is_bear || is_climax)
|
if(is_bull || is_bear || is_climax)
|
||||||
{
|
{
|
||||||
// Mark Arrow
|
// Arrows
|
||||||
if(is_bull)
|
if(is_bull)
|
||||||
BufBull[i] = low[i] - atr * 0.5;
|
BufBull[i] = low[i] - atr*0.3;
|
||||||
if(is_bear)
|
if(is_bear)
|
||||||
BufBear[i] = high[i] + atr * 0.5;
|
BufBear[i] = high[i] + atr*0.3;
|
||||||
if(is_climax) { /* Maybe draw both or special? */ }
|
|
||||||
|
|
||||||
// Create/Update Zone Object
|
// ZONES (Rectangles)
|
||||||
string name = "AbsZone_" + TimeToString(time[i]);
|
string name = "AbsZone_" + TimeToString(time[i]);
|
||||||
color zone_col = is_bull ? clrGreen : (is_bear ? clrRed : clrGold);
|
color zone_col = is_bull ? C'0,64,0' : (is_bear ? C'64,0,0' : C'184,134,11'); // Dark Green/Red/Gold
|
||||||
if(is_bull)
|
|
||||||
zone_col = C'0,64,0'; // Darker Green for fill
|
|
||||||
if(is_bear)
|
|
||||||
zone_col = C'64,0,0'; // Darker Red
|
|
||||||
|
|
||||||
|
// Create if not exists
|
||||||
if(ObjectFind(0, name) < 0)
|
if(ObjectFind(0, name) < 0)
|
||||||
{
|
{
|
||||||
ObjectCreate(0, name, OBJ_RECTANGLE, 0, time[i], high[i], time[i], low[i]);
|
ObjectCreate(0, name, OBJ_RECTANGLE, 0, time[i], high[i], time[i], low[i]);
|
||||||
ObjectSetInteger(0, name, OBJPROP_COLOR, zone_col);
|
ObjectSetInteger(0, name, OBJPROP_COLOR, zone_col);
|
||||||
ObjectSetInteger(0, name, OBJPROP_FILL, true);
|
ObjectSetInteger(0, name, OBJPROP_FILL, true);
|
||||||
ObjectSetInteger(0, name, OBJPROP_BACK, true); // Draw behind candles
|
ObjectSetInteger(0, name, OBJPROP_BACK, true);
|
||||||
ObjectSetInteger(0, name, OBJPROP_WIDTH, 1);
|
ObjectSetInteger(0, name, OBJPROP_WIDTH, 1); // Borderless look if fill
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manage Zone Extension
|
// Extend Logic: Find breaker candle
|
||||||
// Find if/when price broke the zone
|
datetime end_time = time[rates_total-1] + PeriodSeconds()*5; // Default: Live
|
||||||
datetime end_time = time[rates_total-1] + PeriodSeconds()*5; // Default: Live into future
|
|
||||||
|
|
||||||
bool broken = false;
|
bool broken = false;
|
||||||
|
|
||||||
|
// Scan forward from signal bar
|
||||||
for(int k = i + 1; k < rates_total; k++)
|
for(int k = i + 1; k < rates_total; k++)
|
||||||
{
|
{
|
||||||
// Bull Zone broken if Close < Low
|
|
||||||
if(is_bull && close[k] < low[i])
|
if(is_bull && close[k] < low[i])
|
||||||
{
|
{
|
||||||
end_time = time[k];
|
end_time = time[k];
|
||||||
broken = true;
|
broken = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Bear Zone broken if Close > High
|
|
||||||
if(is_bear && close[k] > high[i])
|
if(is_bear && close[k] > high[i])
|
||||||
{
|
{
|
||||||
end_time = time[k];
|
end_time = time[k];
|
||||||
broken = true;
|
broken = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Climax broken if broken either way
|
|
||||||
if(is_climax)
|
if(is_climax)
|
||||||
{
|
{
|
||||||
if(close[k] > high[i] || close[k] < low[i])
|
if(close[k] > high[i] || close[k] < low[i])
|
||||||
@@ -212,14 +199,13 @@ int OnCalculate(const int rates_total,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIX: Use Modifier Index 1 for Time2
|
// Update Time2
|
||||||
ObjectSetInteger(0, name, OBJPROP_TIME, 1, end_time);
|
ObjectSetInteger(0, name, OBJPROP_TIME, 1, end_time);
|
||||||
|
// Optional: Change style if broken
|
||||||
// Visual Polish: If broken, make it lighter or dashed?
|
if(broken)
|
||||||
// For now, standard rectangle.
|
ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_DOT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return(rates_total);
|
return(rates_total);
|
||||||
}
|
}
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
|
|||||||
Reference in New Issue
Block a user