Files

258 lines
12 KiB
Plaintext

//+-------------------------------------------------------------------------------------------------------+
//| Alpha Trend.mq5 |
//| Copyright © 2022, Centaur |
//| https://www.mql5.com/en/users/centaur |
//| |
//|For screenshots and extra info: |
//| https://forex-station.com/viewtopic.php?p=1295492109&sid=16f4baa8018e53a3e71fb54b6b29977b#p1295492109 |
//| |
//+-------------------------------------------------------------------------------------------------------+
#property copyright "Copyright © 2022, Centaur"
#property link "https://www.mql5.com/en/users/centaur"
#property version "1.00"
#property indicator_chart_window
#property indicator_buffers 16
#property indicator_plots 3
//--- plot alpha line and offset line
#property indicator_label1 "Alpha Line;Offset Line"
#property indicator_type1 DRAW_FILLING
#property indicator_color1 clrDodgerBlue,clrTomato
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//--- plot Buy Signal
#property indicator_label2 "Buy Signal"
#property indicator_type2 DRAW_ARROW
#property indicator_color2 clrDodgerBlue
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
//--- plot Sell Signal
#property indicator_label3 "Sell Signal"
#property indicator_type3 DRAW_ARROW
#property indicator_color3 clrTomato
#property indicator_style3 STYLE_SOLID
#property indicator_width3 1
//--- enumerations
enum ENUM_YES_NO
{
Yes,
No
};
//--- input parameters
input int inp_length = 14; // Length
input double inp_atr_multiplier = 1.0; // ATR Multiplier
input ENUM_APPLIED_PRICE inp_price = PRICE_CLOSE; // Applied Price
input ENUM_YES_NO inp_change_calc = No; // Use volume data ?
input ENUM_YES_NO inp_signals = Yes; // Show Signals ?
//--- indicator plot buffers
double Alpha[];
double Offset[];
double Buy_Signal[];
double Sell_Signal[];
//--- indicator calculation buffers
double TR[];
double ATR[];
double RSI[];
double MFI[];
double UpTrend[];
double DownTrend[];
double Alpha_Calc[];
double Buy_Signal_Calc[];
double Sell_Signal_Calc[];
double Buy_BarCount[];
double Sell_BarCount[];
double Arrows[];
//--- indicator variables
int length;
double atr_multiplier;
int TR_Handle;
int RSI_Handle;
int MFI_Handle;
string g_signal_prefix;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- check input parameters
length = inp_length < 1 ? 1 : inp_length;
atr_multiplier = inp_atr_multiplier < 0.1 ? 0.1 : NormalizeDouble(inp_atr_multiplier, 1);
//--- indicator buffers mapping
SetIndexBuffer(0, Alpha, INDICATOR_DATA);
SetIndexBuffer(1, Offset, INDICATOR_DATA);
SetIndexBuffer(2, Buy_Signal, INDICATOR_DATA);
SetIndexBuffer(3, Sell_Signal, INDICATOR_DATA);
SetIndexBuffer(4, TR, INDICATOR_CALCULATIONS);
SetIndexBuffer(5, ATR, INDICATOR_CALCULATIONS);
SetIndexBuffer(6, RSI, INDICATOR_CALCULATIONS);
SetIndexBuffer(7, MFI, INDICATOR_CALCULATIONS);
SetIndexBuffer(8, UpTrend, INDICATOR_CALCULATIONS);
SetIndexBuffer(9, DownTrend, INDICATOR_CALCULATIONS);
SetIndexBuffer(10, Alpha_Calc, INDICATOR_CALCULATIONS);
SetIndexBuffer(11, Buy_Signal_Calc, INDICATOR_CALCULATIONS);
SetIndexBuffer(12, Sell_Signal_Calc, INDICATOR_CALCULATIONS);
SetIndexBuffer(13, Buy_BarCount, INDICATOR_CALCULATIONS);
SetIndexBuffer(14, Sell_BarCount, INDICATOR_CALCULATIONS);
SetIndexBuffer(15, Arrows, INDICATOR_CALCULATIONS);
//--- set indicator accuracy
IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
//--- set indicator name display
string prices = inp_price == PRICE_OPEN ? "Open" : inp_price == PRICE_HIGH ? "High" : inp_price == PRICE_LOW ? "Low" : inp_price == PRICE_CLOSE ? "Close" : inp_price == PRICE_MEDIAN ? "Median" : inp_price == PRICE_TYPICAL ? "Typical" : inp_price == PRICE_WEIGHTED ? "Weighted" : " ";
string short_name = "Alpha Trend (" + IntegerToString(length) + ", " + DoubleToString(atr_multiplier, 1) + ", " + prices + ", " + EnumToString(inp_change_calc) + ", " + EnumToString(inp_signals) + ")";
IndicatorSetString(INDICATOR_SHORTNAME, short_name);
//--- sets drawing lines to empty value
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE);
PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, EMPTY_VALUE);
//--- initialize buffers
ArrayInitialize(Alpha, EMPTY_VALUE);
ArrayInitialize(Offset, EMPTY_VALUE);
ArrayInitialize(Buy_Signal, EMPTY_VALUE);
ArrayInitialize(Sell_Signal, EMPTY_VALUE);
ArrayInitialize(TR, 0.0);
ArrayInitialize(ATR, 0.0);
ArrayInitialize(RSI, 0.0);
ArrayInitialize(MFI, 0.0);
ArrayInitialize(UpTrend, 0.0);
ArrayInitialize(DownTrend, 0.0);
ArrayInitialize(Alpha_Calc, 0.0);
ArrayInitialize(Buy_Signal_Calc, 0.0);
ArrayInitialize(Sell_Signal_Calc, 0.0);
ArrayInitialize(Buy_BarCount, 0.0);
ArrayInitialize(Sell_BarCount, 0.0);
ArrayInitialize(Arrows, 0.0);
//--- setting a code from the Wingdings charset as the property of PLOT_ARROW
PlotIndexSetInteger(1, PLOT_ARROW, 225);
PlotIndexSetInteger(2, PLOT_ARROW, 226);
//--- Set the vertical shift of arrows in pixels
PlotIndexSetInteger(1, PLOT_ARROW_SHIFT, 20);
PlotIndexSetInteger(2, PLOT_ARROW_SHIFT, -20);
//--- create handles
TR_Handle = iATR(_Symbol, _Period, 1);
RSI_Handle = iRSI(_Symbol, _Period, length, inp_price);
MFI_Handle = iMFI(_Symbol, _Period, length, VOLUME_TICK);
if(TR_Handle == INVALID_HANDLE || RSI_Handle == INVALID_HANDLE || MFI_Handle == INVALID_HANDLE)
return(INIT_FAILED);
//--- scope signal keys by symbol, timeframe, and indicator inputs
g_signal_prefix = StringFormat("AT_%s_%s_L%d_A%.1f_C%d_S%d",
_Symbol,
EnumToString(_Period),
length,
atr_multiplier,
(int)inp_change_calc,
(int)inp_signals);
//--- initialization succeeded
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(TR_Handle != INVALID_HANDLE)
IndicatorRelease(TR_Handle);
if(RSI_Handle != INVALID_HANDLE)
IndicatorRelease(RSI_Handle);
if(MFI_Handle != INVALID_HANDLE)
IndicatorRelease(MFI_Handle);
}
//+------------------------------------------------------------------+
//| 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[])
{
//--- check period
if(length <= 1 || length > rates_total)
return(0);
//--- latest data copy
int copy;
if(prev_calculated > rates_total || prev_calculated <= 0)
copy = rates_total;
else
{
copy = rates_total - prev_calculated;
//--- last value is always copied
copy++;
}
//--- populate buffers
if(CopyBuffer(TR_Handle, 0, 0, copy, TR) <= 0)
return(0);
if(CopyBuffer(RSI_Handle, 0, 0, copy, RSI) <= 0)
return(0);
if(CopyBuffer(MFI_Handle, 0, 0, copy, MFI) <= 0)
return(0);
//--- calculate start position
int bar;
if(prev_calculated == 0)
bar = 0;
else
bar = prev_calculated - 1;
//--- main loop
for(int i = bar; i < rates_total && !_StopFlag; i++)
{
if(i > length)
{
//--- calculate alpha trend
ATR[i] = fSMA(i, length, TR);
UpTrend[i] = low[i] - ATR[i] * atr_multiplier;
DownTrend[i] = high[i] + ATR[i] * atr_multiplier;
Alpha_Calc[i] = (inp_change_calc == No ? RSI[i] >= 50 : MFI[i] >= 50) ? UpTrend[i] < Alpha_Calc[i - 1] ? Alpha_Calc[i - 1] : UpTrend[i] : DownTrend[i] > Alpha_Calc[i - 1] ? Alpha_Calc[i - 1] : DownTrend[i];
//--- plot alpha trend
Alpha[i] = NormalizeDouble(Alpha_Calc[i], _Digits);
Offset[i] = NormalizeDouble(Alpha_Calc[i - 2], _Digits);
//--- plot buy and sell signals
Buy_Signal_Calc[i] = Alpha[i] > Offset[i] && Alpha[i - 1] <= Offset[i - 1] ? 1.0 : 0.0;
Sell_Signal_Calc[i] = Alpha[i] < Offset[i] && Alpha[i - 1] >= Offset[i - 1] ? 1.0 : 0.0;
Buy_BarCount[i] = fBarsSince(i, Buy_Signal_Calc);
Sell_BarCount[i] = fBarsSince(i, Sell_Signal_Calc);
Arrows[i] = Buy_BarCount[i] > Sell_BarCount[i] ? 1.0 : -1.0;
Buy_Signal[i] = inp_signals == No ? EMPTY_VALUE : Arrows[i] == -1.0 && Arrows[i - 1] == 1.0 ? Offset[i] : EMPTY_VALUE;
Sell_Signal[i] = inp_signals == No ? EMPTY_VALUE : Arrows[i] == 1.0 && Arrows[i - 1] == -1.0 ? Offset[i] : EMPTY_VALUE;
}
}
//--- write only closed-bar signals to GlobalVariable for Mt5Bridge
int last_closed = rates_total - 2;
if(last_closed > length)
{
GlobalVariableSet(g_signal_prefix + "_Alpha", Alpha[last_closed]);
GlobalVariableSet(g_signal_prefix + "_Offset", Offset[last_closed]);
GlobalVariableSet(g_signal_prefix + "_Trend", Arrows[last_closed]);
GlobalVariableSet(g_signal_prefix + "_Buy", Buy_Signal_Calc[last_closed]);
GlobalVariableSet(g_signal_prefix + "_Sell", Sell_Signal_Calc[last_closed]);
}
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
//| Function: Simple Moving Average (SMA) |
//+------------------------------------------------------------------+
double fSMA(const int _position, const int _period, const double &_input[])
{
double result = 0.0;
double sum = 0.0;
for(int k = 0; k < _period; k++)
sum += _input[_position - k];
result = sum / _period;
return(result);
}
//+------------------------------------------------------------------+
//| Function: Count bars since last event greater than zero |
//+------------------------------------------------------------------+
double fBarsSince(const int _position, const double &_input[])
{
int result = 0;
while(_position - result >= 0 && _input[_position - result] == 0.0)
result++;
return(result);
}
//+------------------------------------------------------------------+