258 lines
12 KiB
Plaintext
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);
|
|
}
|
|
//+------------------------------------------------------------------+
|