forked from 93744399/FMIC
289 lines
15 KiB
MQL5
289 lines
15 KiB
MQL5
//---------------------------------------------------------------------------------------------------------------------
| |||
#define MName "Time Segmented Volume (TSV)"
| |||
#define MVersion "1.01"
| |||
#define MBuild "2023-03-27 21:02 WET"
| |||
#define MCopyright "Copyright \x00A9 2023, Fernando M. I. Carreiro, All rights reserved"
| |||
#define MProfile "https://www.mql5.com/en/users/FMIC"
| |||
//---------------------------------------------------------------------------------------------------------------------
| |||
#property strict
| |||
#property version MVersion
| |||
#property description MName
| |||
#property description "MetaTrader Indicator (Build "MBuild")"
| |||
#property copyright MCopyright
| |||
#property link MProfile
| |||
//---------------------------------------------------------------------------------------------------------------------
| |||
| |||
//--- Setup
| |||
| |||
#property indicator_separate_window
| |||
| |||
// Define number of buffers and plots
| |||
#define MPlots 3
| |||
#define MBuffers 7
| |||
#ifdef __MQL4__
| |||
#property indicator_buffers ( MPlots + 1 )
| |||
#else
| |||
#property indicator_buffers MBuffers
| |||
#property indicator_plots MPlots
| |||
#endif
| |||
| |||
// Define plot colours and respective indices
| |||
#define MClrCandleNone C'239,166,117'
| |||
#define MClrCandleUp C'38,166,154'
| |||
#define MClrCandleDown C'239,83,80'
| |||
| |||
// Display properties for plots
| |||
#ifdef __MQL4__
| |||
// Summation plots
| |||
#property indicator_label1 "Summation (positive)"
| |||
#property indicator_type1 DRAW_HISTOGRAM
| |||
#property indicator_style1 STYLE_SOLID
| |||
#property indicator_width1 3
| |||
#property indicator_color1 MClrCandleUp
| |||
#property indicator_label2 "Summation (negative)"
| |||
#property indicator_type2 DRAW_HISTOGRAM
| |||
#property indicator_style2 STYLE_SOLID
| |||
#property indicator_width2 3
| |||
#property indicator_color2 MClrCandleDown
| |||
// Simple averaging plot
| |||
#property indicator_label3 "Averaging (simple)"
| |||
#property indicator_type3 DRAW_LINE
| |||
#property indicator_style3 STYLE_SOLID
| |||
#property indicator_width3 2
| |||
#property indicator_color3 MClrCandleNone
| |||
// Exponential averaging plot
| |||
#property indicator_label4 "Averaging (exponential)"
| |||
#property indicator_type4 DRAW_LINE
| |||
#property indicator_style4 STYLE_SOLID
| |||
#property indicator_width4 1
| |||
#property indicator_color4 MClrCandleNone
| |||
#else
| |||
// Define colour index for plots
| |||
#define MIdxCandleNone 0.0
| |||
#define MIdxCandleUp 1.0
| |||
#define MIdxCandleDown 2.0
| |||
// Summation plot
| |||
#property indicator_label1 "Summation"
| |||
#property indicator_type1 DRAW_COLOR_HISTOGRAM
| |||
#property indicator_style1 STYLE_SOLID
| |||
#property indicator_width1 5
| |||
#property indicator_color1 MClrCandleNone, MClrCandleUp, MClrCandleDown
| |||
// Simple averaging plot
| |||
#property indicator_label2 "Averaging (simple)"
| |||
#property indicator_type2 DRAW_LINE
| |||
#property indicator_style2 STYLE_SOLID
| |||
#property indicator_width2 2
| |||
#property indicator_color2 MClrCandleNone
| |||
// Exponential averaging plot
| |||
#property indicator_label3 "Averaging (exponential)"
| |||
#property indicator_type3 DRAW_LINE
| |||
#property indicator_style3 STYLE_SOLID
| |||
#property indicator_width3 1
| |||
#property indicator_color3 MClrCandleNone
| |||
#endif
| |||
| |||
//--- Enumarations
| |||
| |||
// Volume weight enumaraton
| |||
enum EVolumeWeight
| |||
{
| |||
EVW_None = 0, // No volume weighting
| |||
EVW_TickVolume, // Tick volume
| |||
#ifndef __MQL4__
| |||
EVW_RealVolume, // Real volume
| |||
#endif
| |||
EVW_PriceRange // True price range (pseudo volume)
| |||
};
| |||
| |||
//--- Parameter settings
| |||
| |||
input uint i_nSummationPeriod = 13, // Summation period
| |||
i_nAveragingPeriod = 7; // Averaging period
| |||
input ENUM_APPLIED_PRICE i_ePriceApplied = PRICE_CLOSE; // Applied price
| |||
input EVolumeWeight i_eVolumeWeight = EVW_TickVolume; // Applied volume
| |||
| |||
//--- Macro definitions
| |||
| |||
// Define OnCalculate loop sequencing macros
| |||
#define MOnCalcPrevTest ( prev_calculated < 1 || prev_calculated > rates_total )
| |||
#ifdef __MQL4__ // for MQL4 (as series)
| |||
#define MOnCalcNext( _index ) ( _index-- )
| |||
#define MOnCalcBack( _index, _offset ) ( _index + _offset )
| |||
#define MOnCalcCheck( _index ) ( _index >= 0 )
| |||
#define MOnCalcValid( _index ) ( _index < rates_total )
| |||
#define MOnCalcStart \
| |||
( rates_total - ( MOnCalcPrevTest ? 1 : prev_calculated ) )
| |||
#else // for MQL5 (as non-series)
| |||
#define MOnCalcNext( _index ) ( _index++ )
| |||
#define MOnCalcBack( _index, _offset ) ( _index - _offset )
| |||
#define MOnCalcCheck( _index ) ( _index < rates_total )
| |||
#define MOnCalcValid( _index ) ( _index >= 0 )
| |||
#define MOnCalcStart \
| |||
( MOnCalcPrevTest ? 0 : prev_calculated - 1 )
| |||
#endif
| |||
| |||
// Define applied price macro
| |||
#define MSetAppliedPrice( _type, _where, _index ) { switch( _type ) { \
| |||
case PRICE_WEIGHTED: _where = ( high[ _index ] + low[ _index ] + close[ _index ] \
| |||
+ close[ _index ] ) * 0.25; break; \
| |||
case PRICE_TYPICAL: _where = ( high[ _index ] + low[ _index ] + close[ _index ] ) / 3.0; break; \
| |||
case PRICE_MEDIAN: _where = ( high[ _index ] + low[ _index ] ) * 0.5; break; \
| |||
case PRICE_HIGH: _where = high[ _index ]; break; \
| |||
case PRICE_LOW: _where = low[ _index ]; break; \
| |||
case PRICE_OPEN: _where = open[ _index ]; break; \
| |||
case PRICE_CLOSE: \
| |||
default: _where = close[ _index ]; }; }
| |||
| |||
// Define macro for invalid parameter values
| |||
#define MCheckParameter( _condition, _text ) if( _condition ) \
| |||
{ Print( "Error: Invalid ", _text ); return INIT_PARAMETERS_INCORRECT; }
| |||
| |||
//--- Global variable declarations
| |||
| |||
// Indicator buffers
| |||
double g_adbPriceApplied[], // Buffer for applied price
| |||
g_adbVolumePriceDelta[], // Buffer for volume weight price delta change
| |||
g_adbSummation[], // Buffer for summation of volume weighte price change
| |||
g_adbSummationSimple[], // Buffer for summation of summation for simple averaging
| |||
g_adbAveragingSimple[], // Buffer for simple averaging
| |||
g_adbAveragingExponential[]; // Buffer for exponential averaging
| |||
#ifdef __MQL4__
| |||
double g_adbSummationPositive[], // Buffer for positive summation of volume weighte price change
| |||
g_adbSummationNegative[]; // Buffer for negative summation of volume weighte price change
| |||
#else
| |||
double g_adbSummationColour[]; // Buffer for summation colourisation
| |||
#endif
| |||
| |||
// Miscellaneous global variables
| |||
double g_dbEmaWeight; // Weight to be used for exponential moving averages
| |||
| |||
//--- Event handling functions
| |||
| |||
// Initialisation event handler
| |||
int OnInit(void) {
| |||
// Validate input parameters
| |||
MCheckParameter( i_nSummationPeriod < 1, "summation period" );
| |||
MCheckParameter( i_nAveragingPeriod < 1 ||
| |||
i_nAveragingPeriod > i_nSummationPeriod, "averaging period" );
| |||
| |||
// Calculate parameter variables
| |||
g_dbEmaWeight = 2.0 / ( i_nAveragingPeriod + 1.0 );
| |||
| |||
// Set number of significant digits (precision)
| |||
IndicatorSetInteger( INDICATOR_DIGITS, _Digits );
| |||
| |||
// Set buffers
| |||
int iBuffer = 0;
| |||
#ifdef __MQL4__
| |||
IndicatorBuffers( MBuffers + 1 ); // Set total number of buffers (MQL4 Only)
| |||
SetIndexBuffer( iBuffer++, g_adbSummationPositive, INDICATOR_DATA );
| |||
SetIndexBuffer( iBuffer++, g_adbSummationNegative, INDICATOR_DATA );
| |||
#else
| |||
SetIndexBuffer( iBuffer++, g_adbSummation, INDICATOR_DATA );
| |||
SetIndexBuffer( iBuffer++, g_adbSummationColour, INDICATOR_COLOR_INDEX );
| |||
#endif
| |||
SetIndexBuffer( iBuffer++, g_adbAveragingSimple, INDICATOR_DATA );
| |||
SetIndexBuffer( iBuffer++, g_adbAveragingExponential, INDICATOR_DATA );
| |||
SetIndexBuffer( iBuffer++, g_adbPriceApplied, INDICATOR_CALCULATIONS );
| |||
SetIndexBuffer( iBuffer++, g_adbVolumePriceDelta, INDICATOR_CALCULATIONS );
| |||
SetIndexBuffer( iBuffer++, g_adbSummationSimple, INDICATOR_CALCULATIONS );
| |||
#ifdef __MQL4__
| |||
SetIndexBuffer( iBuffer++, g_adbSummation, INDICATOR_CALCULATIONS );
| |||
#endif
| |||
| |||
// Set indicator name
| |||
IndicatorSetString( INDICATOR_SHORTNAME, StringFormat(
| |||
MName " ( %d, %d )", i_nSummationPeriod, i_nAveragingPeriod ) );
| |||
| |||
return INIT_SUCCEEDED; // Successful initialisation of indicator
| |||
};
| |||
| |||
// Calculation event handler
| |||
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[]
| |||
)
| |||
{
| |||
// Main loop — fill in the arrays with data values
| |||
for( int iCur = MOnCalcStart,
| |||
iPrev = MOnCalcBack( iCur, 1 ),
| |||
iSumPrev = MOnCalcBack( iCur, (int) i_nSummationPeriod ),
| |||
iAvgPrev = MOnCalcBack( iCur, (int) i_nAveragingPeriod );
| |||
!IsStopped() && MOnCalcCheck( iCur );
| |||
MOnCalcNext( iCur ), MOnCalcNext( iPrev ), MOnCalcNext( iSumPrev ), MOnCalcNext( iAvgPrev ) )
| |||
{
| |||
// Calculate volume to apply
| |||
double dbVolume = 1.0;
| |||
switch( i_eVolumeWeight ) {
| |||
#ifndef __MQL4__
| |||
case EVW_RealVolume: dbVolume = (double) volume[ iCur ]; break;
| |||
#endif
| |||
case EVW_TickVolume: dbVolume = (double) tick_volume[ iCur ]; break;
| |||
case EVW_PriceRange: if( MOnCalcValid( iPrev ) ) {
| |||
double dbClosePrev = close[ iPrev ];
| |||
dbVolume = fmax( high[ iCur ], dbClosePrev )
| |||
- fmin( low[ iCur ], dbClosePrev );
| |||
} else dbVolume = high[ iCur ] - low[ iCur ];
| |||
};
| |||
| |||
// Calculate price to apply
| |||
double dbPriceCur;
| |||
MSetAppliedPrice( i_ePriceApplied, dbPriceCur, iCur );
| |||
| |||
// Calculate volume weighted price delta and sum
| |||
double dbPricePrev = MOnCalcValid( iPrev ) ? g_adbPriceApplied [ iPrev ] : open[ iCur ],
| |||
dbPriceDelta = dbPriceCur - dbPricePrev,
| |||
dbVolumePriceDelta = dbPriceDelta * dbVolume,
| |||
dbSummation = dbVolumePriceDelta
| |||
+ ( MOnCalcValid( iPrev ) ? g_adbSummation[ iPrev ] : 0.0 )
| |||
- ( MOnCalcValid( iSumPrev ) ? g_adbVolumePriceDelta[ iSumPrev ] : 0.0 );
| |||
// Define colourasation
| |||
#ifdef __MQL4__
| |||
double dbSummationPositive = dbSummation > 0.0 ? dbSummation : 0.0,
| |||
dbSummationNegative = dbSummation < 0.0 ? dbSummation : 0.0;
| |||
#else
| |||
double dbSummationColour = dbSummation > 0.0 ? MIdxCandleUp
| |||
: ( dbSummation < 0.0 ? MIdxCandleDown
| |||
: MIdxCandleNone );
| |||
#endif
| |||
| |||
// Calculate simple summation and averaging
| |||
double dbSumSimpleCur = dbSummation
| |||
+ ( MOnCalcValid( iPrev ) ? g_adbSummationSimple[ iPrev ] : 0.0 )
| |||
- ( MOnCalcValid( iAvgPrev ) ? g_adbSummation[ iAvgPrev ] : 0.0 ),
| |||
dbAverageSimpleCur = dbSumSimpleCur / i_nAveragingPeriod;
| |||
| |||
// Calculate exponential averaging
| |||
double dbAverageExponentialPrev = MOnCalcValid( iPrev ) ? g_adbAveragingExponential[ iPrev ] : dbSummation,
| |||
dbAverageExponentialCur = dbAverageExponentialPrev
| |||
+ ( dbSummation - dbAverageExponentialPrev )
| |||
* g_dbEmaWeight;
| |||
| |||
// Set buffer values
| |||
g_adbPriceApplied[ iCur ] = dbPriceCur;
| |||
g_adbVolumePriceDelta[ iCur ] = dbVolumePriceDelta;
| |||
g_adbSummation[ iCur ] = dbSummation;
| |||
g_adbSummationSimple[ iCur ] = dbSumSimpleCur;
| |||
g_adbAveragingSimple[ iCur ] = dbAverageSimpleCur;
| |||
g_adbAveragingExponential[ iCur ] = dbAverageExponentialCur;
| |||
#ifdef __MQL4__
| |||
g_adbSummationPositive[ iCur ] = dbSummationPositive;
| |||
g_adbSummationNegative[ iCur ] = dbSummationNegative;
| |||
#else
| |||
g_adbSummationColour[ iCur ] = dbSummationColour;
| |||
#endif
| |||
};
| |||
| |||
return rates_total; // Return value for prev_calculated of next call
| |||
};
| |||
| |||
//---------------------------------------------------------------------------------------------------------------------
|