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

146 lines
12 KiB
MQL5
Raw Permalink Normal View History

2026-03-24 20:26:12 +07:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| FVE.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 description "Finite Volume Elements"
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots 1
//--- plot FVE
#property indicator_label1 "FVE"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrRed
#property indicator_style1 STYLE_SOLID
#property indicator_width1 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="Used Volume") ENUM_USED_VOLUME InpUsedVolume = USED_VOLUME_TICK; // A?>;L7C5<K9 >1JQ<
//--- indicator buffers
double BufferFVE[];
double BufferVolumePlusMinus[];
double BufferVolumes[];
//--- global variables
int samples;
double cutoff;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,BufferFVE,INDICATOR_DATA);
SetIndexBuffer(1,BufferVolumePlusMinus,INDICATOR_CALCULATIONS);
SetIndexBuffer(2,BufferVolumes,INDICATOR_CALCULATIONS);
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,EMPTY_VALUE);
//--- @>25@:0 8 CAB0=>2:0 ?5@8>40 8 ?>@>30
samples=(InpSamples<1? 22 : InpSamples);
cutoff=InpCutOff/100.0;
//--- #AB0=>2:0 8<5=8 8=48:0B>@0 8 C@>2=O 0
IndicatorSetString(INDICATOR_SHORTNAME,StringFormat("FVE(%d,%.3f)",samples,InpCutOff));
IndicatorSetInteger(INDICATOR_LEVELS,1);
IndicatorSetDouble(INDICATOR_LEVELVALUE,0,0.0);
ArraySetAsSeries(BufferFVE,true);
ArraySetAsSeries(BufferVolumePlusMinus,true);
ArraySetAsSeries(BufferVolumes,true);
//--- AQ CA?5H=>
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+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 >G5@54=>9 =>2K9 B8: - =8G53> =5 45;05<
if(limit==0)
return(rates_total);
//--- A;8 ?5@2K9 70?CA: 8;8 87<5=5=8O 8AB>@8G5A:8E 40==KE
if(limit>1)
{
//--- @0AGQB =0G8=05< >B =0G0;0 8AB>@8G5A:8E 40==KE,
//--- 8=8F80;878@C5< 1CD5@K 8=48:0B>@0 =C;52K<8 7=0G5=8O<8
limit=rates_total-samples-1;
ArrayInitialize(BufferFVE,0);
ArrayInitialize(BufferVolumePlusMinus,0);
ArrayInitialize(BufferVolumes,0);
}
//--- 0AGQB 8=48:0B>@0 (;81> 2AO 8AB>@8O, ;81> :064K9 >G5@54=>9 =>2K9 10@)
for(int i=limit; i>=0; i--)
{
//--- "8?8G=K5 F5=K 4;O B5:CI53> 8 ?@54K4CI53> 10@>2
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
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
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
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);
}
//--- return value of prev_calculated for next call
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]);
}
//+------------------------------------------------------------------+