Article-20940-MQL5-Finite-V.../FinVolEleLinRegSl.mq5

193 行
15 KiB
MQL5

2026-03-24 20:26:12 +07:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| FinVolEleLinRegSl.mq5 |
//| Copyright 2026, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#property indicator_separate_window
#property description "Finite Volume Elements + Linear Regression Slope"
#property indicator_buffers 5
#property indicator_plots 2
//--- plot FVESlope
#property indicator_label1 "FVESlope"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrRed
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//--- plot PriceSlope
#property indicator_label2 "PriceSlope"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrBlue
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
enum ENUM_USED_VOLUME // 5@5G8A;5=85 8A?>;L7C5<KE >1JQ<>2
{
USED_VOLUME_REAL, // Real Volume
USED_VOLUME_TICK, // Tick Volume
};
//--- input parameters
input(name="Samples") int InpSamples = 22; // 5@8>4 @0AGQB0
input(name="Threshold") double InpCutOff = 0.3; // >@>3 GC2AB28B5;L=>AB8
input(name="SlopePeriod") int InpSlopePeriod = 35; // 5@8>4 ;8=59=>9 @53@5AA88
input(name="PriceSlopeFactor")double InpPriceSlopeFactor = 2500; // 0AHB01 F5=K (8=48284C0;L=> ?>4 8=AB@C<5=B)
input(name="Used Volume") ENUM_USED_VOLUME InpUsedVolume = USED_VOLUME_TICK; // A?>;L7C5<K9 >1JQ<
//--- indicator buffers
double BufferFVESlope[];
double BufferPriceSlope[];
double BufferFVE[];
double BufferVolumePlusMinus[];
double BufferVolumes[];
//--- global variables
int samples;
double cutoff;
int slope_period;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- >B>1@0605<K5 1CD5@K
SetIndexBuffer(0,BufferFVESlope,INDICATOR_DATA);
SetIndexBuffer(1,BufferPriceSlope,INDICATOR_DATA);
//--- @0AGQB=K5 1CD5@K
SetIndexBuffer(2,BufferFVE,INDICATOR_CALCULATIONS);
SetIndexBuffer(3,BufferVolumePlusMinus,INDICATOR_CALCULATIONS);
SetIndexBuffer(4,BufferVolumes,INDICATOR_CALCULATIONS);
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,EMPTY_VALUE);
PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,EMPTY_VALUE);
samples=(InpSamples<1? 22 : InpSamples);
cutoff=InpCutOff/100.0;
slope_period=(InpSlopePeriod<2? 35 : InpSlopePeriod);
//--- >@>B:>5 8<O 8=48:0B>@0
IndicatorSetString(INDICATOR_SHORTNAME,
StringFormat("FVELinReg(%d,%.3f,%d,%.1f)",samples,InpCutOff,slope_period,InpPriceSlopeFactor));
//--- #@>25=L 0 8=48:0B>@0
IndicatorSetInteger(INDICATOR_LEVELS,1);
IndicatorSetDouble(INDICATOR_LEVELVALUE,0,0.0);
ArraySetAsSeries(BufferFVE,true);
ArraySetAsSeries(BufferVolumePlusMinus,true);
ArraySetAsSeries(BufferVolumes,true);
ArraySetAsSeries(BufferFVESlope,true);
ArraySetAsSeries(BufferPriceSlope,true);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int32_t rates_total,
const int32_t 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 int32_t &spread[])
{
//--- @>25@:0 :>;8G5AB20 4>ABC?=KE 10@>2
if(rates_total<samples+slope_period+1)
return(0);
//--- 0AA82K 4;O @0AGQB0 - :0: B09<A5@88
ArraySetAsSeries(high,true);
ArraySetAsSeries(low,true);
ArraySetAsSeries(close,true);
ArraySetAsSeries(volume,true);
ArraySetAsSeries(tick_volume,true);
//--- @>25@:0 8 @0AGQB :>;8G5AB20 ?@>AG8BK205<KE 10@>2
int limit=rates_total-prev_calculated;
//--- A;8 ?5@2K9 70?CA: 8;8 87<5=5=8O 8AB>@8G5A:8E 40==KE
if(limit>1)
{
limit=rates_total-samples-slope_period-1;
ArrayInitialize(BufferFVE,0);
ArrayInitialize(BufferVolumePlusMinus,0);
ArrayInitialize(BufferVolumes,0);
ArrayInitialize(BufferFVESlope,0);
ArrayInitialize(BufferPriceSlope,0);
}
//--- 0AGQB 8=48:0B>@0
for(int i=limit; i>=0; i--)
{
//--- "8?8G=K5 F5=K 4;O B5:CI53> 8 ?@54K4CI53> 10@>2 (FVE)
double TP_curr=(high[i]+low[i]+close[i])/3.0;
double TP_prev=(high[i+1]+low[i+1]+close[i+1])/3.0;
//--- 0AAG8BK205< B5:CI85 <5B@8:C 8 =0?@02;5=85 42865=8O F5=K (FVE)
double MF=(close[i]-(high[i]+low[i])/2.0)+TP_curr-TP_prev;
int FveFactor=(MF>cutoff*close[i]) ? 1 : (MF< -cutoff*close[i]) ? -1 : 0;
//--- 0?8AK205< B5:CI85 A:>@@5:B8@>20==K9 8 >1I89 >1JQ<K 2 1CD5@K (FVE)
long vol=Volume(i,volume,tick_volume);
BufferVolumePlusMinus[i]=double(vol*FveFactor);
BufferVolumes[i]=(double)vol;
//--- !C<<8@C5< A:>@@5:B8@>20==K9 8 >1I89 >1JQ< 70 samples 10@>2 (FVE)
double FVEsum=0, VolSum=0;
for(int j=0;j<samples;j++)
{
int idx=i+j;
FVEsum+=BufferVolumePlusMinus[idx]; // !C<<0 A:>@@5:B8@>20==>3> >1JQ<0 70 samples 10@>2
VolSum+=BufferVolumes[idx]; // !C<<0 >1I53> >1JQ<0 70 samples 10@>2
}
//--- 0AAG8BK205< FVE
BufferFVE[i]=(VolSum!=0 ? (FVEsum/VolSum)*100.0 : 0.0);
// --- 8=59=0O @53@5AA8O ?> FVE 8 ?> F5=5
if(i<=rates_total-samples-slope_period-1)
{
BufferFVESlope[i]=LinearRegSlope(BufferFVE,i,slope_period);
BufferPriceSlope[i]=LinearRegSlope(close,i,slope_period)*InpPriceSlopeFactor;
}
else
{
BufferFVESlope[i]=EMPTY_VALUE;
BufferPriceSlope[i]=EMPTY_VALUE;
}
}
return(rates_total);
}
//+------------------------------------------------------------------+
//| >72@0I05B >1JQ< 2 7028A8<>AB8 >B 2K1@0==>3> 2 =0AB@>9:0E |
//+------------------------------------------------------------------+
long Volume(const int index,const long &volume_real[],const long &volume_tick[])
{
return(InpUsedVolume==USED_VOLUME_REAL ? volume_real[index] : volume_tick[index]);
}
//+------------------------------------------------------------------+
//| 0AGQB =0:;>=0 ;8=59=>9 @53@5AA88 4;O <0AA820 buffer |
//+------------------------------------------------------------------+
double LinearRegSlope(const double &buffer[],int start,int period)
{
bool as_series=ArrayGetAsSeries(buffer);
double sumX=0,sumY=0,sumXY=0,sumXX=0;
for(int i=0;i<period;i++)
{
double x=i;
double y=(as_series ? buffer[start+period-1-i] : buffer[start+i]);
sumX+=x;
sumY+=y;
sumXY+=x*y;
sumXX+=x*x;
}
double denom=period*sumXX-sumX*sumX;
if(denom==0) return(0.0);
double slope=(period*sumXY-sumX*sumY)/denom;
return(slope);
}
//+------------------------------------------------------------------+