Compare commits

..

21 Commits

Author SHA1 Message Date
Artur 380071b195 version 3.14 2021-04-28 17:27:12 +02:00
Artur a73e2c0713 Updated for compatibility with ver 3.11 2020-09-29 11:26:32 +02:00
9nix6 3175f594f1 Update README.md 2020-05-21 20:48:41 +02:00
Artur 5327473eaf Updated for RangeBars ver. 3.04 2020-03-17 23:34:45 +01:00
unknown 8035947476 Updated for RangeBars ver. 3.03 2020-03-11 17:04:08 +01:00
unknown acba19e38f Updated for RangeBars ver. 3.02 2020-02-25 18:25:11 +01:00
unknown 0d51499dcf Updated for RangeBars ver. 3.01 2020-02-23 23:23:36 +01:00
unknown e6121f7487 Updated for RangeBars ver. 3.00 2020-02-23 16:21:15 +01:00
unknown bd957ab1af updated Smoothalgorithms.mqh 2020-01-15 22:30:38 +01:00
unknown 0ba2c53a35 Merge branch 'master' of https://github.com/9nix6/Range-Bars-Charting 2019-09-30 13:03:01 +02:00
unknown dde1849bb0 added OBV indicator 2019-09-30 13:02:46 +02:00
9nix6 e4e0bb483a Fixed RageBar indicator path 2019-08-28 20:59:48 +02:00
unknown b784e9556d Merge branch 'master' of https://github.com/9nix6/Range-Bars-Charting 2019-08-25 22:22:29 +02:00
unknown 695a66b812 update for version 2.13 2019-08-25 22:20:16 +02:00
9nix6 bd3a18958e Fixed error on line 99 2019-07-12 22:43:13 +02:00
9nix6 dd2f769c89 Update for version 2.11 2019-05-14 17:22:40 +02:00
9nix6 38937ddce1 new version update 2018-12-13 00:19:34 +01:00
9nix6 75a0f76352 Added MACD Line indicator 2018-07-16 12:51:08 +02:00
9nix6 4f56445d60 Updated TimeLine indicator 2018-06-01 17:01:39 +02:00
9nix6 a23213f3e1 Added time line indicator 2018-05-28 19:38:04 +02:00
9nix6 91e99e93cc Update to version 2.04 2018-05-15 19:27:24 +02:00
139 changed files with 8936 additions and 1213 deletions
Binary file not shown.
+419
View File
@@ -0,0 +1,419 @@
#property copyright "Copyright 2017-2021, Artur Zas"
// GNU General Public License v3.0 -> https://github.com/9nix6/Median-and-Turbo-Renko-indicator-bundle/blob/master/LICENSE
#property link "https://www.az-invest.eu"
#property version "1.17"
#property description "Example EA: Trading based on 2 moving average crossover."
#property description "MA1 & MA2 need to be enabled on the inicator creating the chart."
#property description "MA1 - Fast moving average"
#property description "MA2 - Slow moving average"
//#define ULTIMATE_RENKO_LICENSE // uncomment when used on Ultimate Renko chart from https://www.az-invest.eu/ultimate-renko-indicator-generator-for-metatrader-5
//#define VOLUMECHART_LICENSE // uncomment when used on a Tick & Volume bar chart from https://www.az-invest.eu/Tick-chart-and-volume-chart-for-mt5
//#define RANGEBAR_LICENSE // uncomment when used on a Tick & Volume bar chart from https://www.az-invest.eu/rangebars-for-metatrader-5
//#define SECONDSCHART_LICENSE // uncomment when used on a Seconds TF bar chart from https://www.az-invest.eu/seconds-timeframe-chart-for-metatrader-5
//#define LINEBREAKCHART_LICENSE // uncomment when used on a Line Break chart from https://www.az-invest.eu
//
// Uncomment only ONE of the 5 directives listed below and recompile
// -----------------------------------------------------------------
//
#define EA_ON_RANGE_BARS // Use EA on RangeBar chart
//#define EA_ON_RENKO // Use EA on Renko charts
//#define EA_ON_XTICK_CHART // Use EA on XTick Chart (obsolete)
//#define EA_ON_TICK_VOLUME_CHART // Use EA on Tick & Volume Bar Chart
//#define EA_ON_SECONDS_CHART // Use EA on Seconds Interval chart
//#define EA_ON_LINEBREAK_CHART // Use EA on LineBreak charts
//#define DEVELOPER_VERSION // used when I develop ;) should always be commented out
// Uncomment the directive below and recompile if EA is used with P-Renko BR Ultimate
// ----------------------------------------------------------------------------------
//
// #define P_RENKO_BR_PRO // Use in P-Renko BR Ultimate version
//
// Uncomment the directive below and recompile for use in a backtest only
// ----------------------------------------------------------------------
//
// #define SHOW_INDICATOR_INPUTS
// Include all needed files
#ifdef EA_ON_RANGE_BARS
#include <AZ-INVEST/SDK/RangeBars.mqh>
RangeBars *customBars = NULL;
#endif
#ifdef EA_ON_RENKO
#include <AZ-INVEST/SDK/MedianRenko.mqh>
MedianRenko *customBars = NULL;
#endif
#ifdef EA_ON_XTICK_CHART
#include <AZ-INVEST/SDK/TickChart.mqh>
TickChart *customBars = NULL;
#endif
#ifdef EA_ON_TICK_VOLUME_CHART
#include <AZ-INVEST/SDK/VolumeBarChart.mqh>
TickChart *customBars = NULL;
#endif
#ifdef EA_ON_SECONDS_CHART
#include <AZ-INVEST/SDK/SecondsChart.mqh>
SecondsChart *customBars = NULL;
#endif
#ifdef EA_ON_LINEBREAK_CHART
#include <AZ-INVEST/SDK/LineBreakChart.mqh>
LineBreakChart *customBars = NULL;
#endif
#include <AZ-INVEST/SDK/TimeControl.mqh>
#include <AZ-INVEST/SDK/TradeFunctions.mqh>
enum ENUM_TRADE_DIRECTION
{
TRADE_DIRECTION_BUY = POSITION_TYPE_BUY, // Buy
TRADE_DIRECTION_SELL = POSITION_TYPE_SELL, // Sell
TRADE_DIRECTION_ALL = 1000, // Buy & Sell
};
#ifdef SHOW_INDICATOR_INPUTS
input group "EA parameters"
#endif
input double Lots = 0.1; // Traded lots
input uint StopLoss = 100; // Stop Loss (in points)
input uint TakeProfit = 250; // Take profit (in points)
input ENUM_TRADE_DIRECTION ValidTradeDirection = TRADE_DIRECTION_ALL; // Valid trading type
input bool ForceSR = false; // Force Stop & Reverse
input bool ReverseOnMACrossInsideGap = true; // Reverse trade if MA cross inside a gap
input bool CloseTradeAfterTradingHours = true; // Close trade after trading hours
input ulong DeviationPoints = 0; // Maximum defiation (in points)
input double ManualTickSize = 0.000; // Tick Size (0 = auto detect)
input string Start="9:00"; // Start trading at
input string End="17:55"; // End trading at
input ulong MagicNumber=5150; // Assign trade ID
input int NumberOfRetries = 50; // Maximum number of retries
input int BusyTimeout_ms = 1000; // Wait [ms] before retry on bussy errors
input int RequoteTimeout_ms = 250; // Wait [ms] before retry on requotes
// Global data buffers
double MA1[]; // Buffer for moving average 1
double MA2[]; // Buffer for moving average 2
// Read 3 rates & 3 MA values starting from current (uncompleted) bar
int startAtBar = 0;
int numberOfBars = 3;
// EA variables
CMarketOrder *marketOrder = NULL;
CTimeControl *timeControl = NULL;
ulong currentTicket;
ENUM_POSITION_TYPE currentPositionType;
ENUM_POSITION_TYPE signal;
ENUM_POSITION_TYPE validation;
#ifdef EA_ON_RANGE_BARS
static int _MA1 = RANGEBAR_MA1;
static int _MA2 = RANGEBAR_MA2;
#endif
#ifdef EA_ON_RENKO
static int _MA1 = RENKO_MA1;
static int _MA2 = RENKO_MA2;
#endif
#ifdef EA_ON_XTICK_CHART
static int _MA1 = TICKCHART_MA1;
static int _MA2 = TICKCHART_MA2;
#endif
#ifdef EA_ON_TICK_VOLUME_CHART
static int _MA1 = VOLUMECHART_MA1;
static int _MA2 = VOLUMECHART_MA2;
#endif
#ifdef EA_ON_SECONDS_CHART
static int _MA1 = SECONDS_MA1;
static int _MA2 = SECONDS_MA2;
#endif
#ifdef EA_ON_LINEBREAK_CHART
static int _MA1 = LINEBREAK_MA1;
static int _MA2 = LINEBREAK_MA2;
#endif
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
if(customBars == NULL)
{
#ifdef EA_ON_RANGE_BARS
customBars = new RangeBars(MQLInfoInteger((int)MQL5_TESTING) ? false : true);
#endif
#ifdef EA_ON_RENKO
customBars = new MedianRenko(MQLInfoInteger((int)MQL5_TESTING) ? false : true);
#endif
#ifdef EA_ON_XTICK_CHART
customBars = new TickChart(MQLInfoInteger((int)MQL5_TESTING) ? false : true);
#endif
#ifdef EA_ON_TICK_VOLUME_CHART
customBars = new TickChart(MQLInfoInteger((int)MQL5_TESTING) ? false : true);
#endif
#ifdef EA_ON_SECONDS_CHART
customBars = new SecondsChart(MQLInfoInteger((int)MQL5_TESTING) ? false : true);
#endif
#ifdef EA_ON_LINEBREAK_CHART
customBars = new LineBreakChart(MQLInfoInteger((int)MQL5_TESTING) ? false : true);
#endif
}
customBars.Init();
if(customBars.GetHandle() == INVALID_HANDLE)
return(INIT_FAILED);
signal = POSITION_TYPE_NONE;
CMarketOrderParameters params;
{
params.m_async_mode = false;
params.m_magic = MagicNumber;
params.m_deviation = DeviationPoints;
params.m_type_filling = ORDER_FILLING_FOK;
params.numberOfRetries = NumberOfRetries;
params.busyTimeout_ms = BusyTimeout_ms;
params.requoteTimeout_ms = RequoteTimeout_ms;
}
marketOrder = new CMarketOrder(params);
if(timeControl == NULL)
{
timeControl = new CTimeControl();
}
timeControl.SetValidTraingHours(Start,End);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
customBars.Deinit();
// delete TimeControl class
if(timeControl != NULL)
{
delete timeControl;
timeControl = NULL;
}
// delete MarketOrder class
if(marketOrder != NULL)
{
delete marketOrder;
marketOrder = NULL;
}
// delete MedianRenko class
if(customBars != NULL)
{
delete customBars;
customBars = NULL;
}
Comment("");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
if(marketOrder == NULL || customBars == NULL || timeControl == NULL)
return;
if(customBars.IsNewBar())
{
if(timeControl.IsScheduleEnabled())
{
Comment("EA trading schedule ON ("+Start+" to "+End+") | trading enabled = "+(string)timeControl.IsTradingTimeValid());
}
else
{
Comment("EA trading schedule OFF");
}
if(!timeControl.IsTradingTimeValid())
{
if(marketOrder.IsOpen(currentTicket,_Symbol,MagicNumber))
{
if(currentTicket > 0 && CloseTradeAfterTradingHours)
{
// close position outside of trading hours
marketOrder.Close(currentTicket);
}
}
return;
}
//
// Get moving average values for current, last completed bar and the bar before that...
//
if(!customBars.GetMA(_MA1,MA1,startAtBar,numberOfBars))
{
Print("Error getting values from MA1 - please enable MA1 on chart");
}
else if(!customBars.GetMA(_MA2,MA2,startAtBar,numberOfBars))
{
Print("Error getting values from MA2 - please enable MA2 on chart");
}
else
{
signal = MovingAverageCross();
validation = MovingAverageValidation();
if(timeControl.IsScheduleEnabled())
{
Comment("EA trading schedule ("+Start+" to "+End+") | trading enabled = "+(string)timeControl.IsTradingTimeValid()+
"\n MA1 [2]: "+DoubleToString(MA1[2],_Digits)+" [1]: "+DoubleToString(MA1[1],_Digits)+
"\n MA2 [2]: "+DoubleToString(MA2[2],_Digits)+" [1]: "+DoubleToString(MA2[1],_Digits)+
"\n MA cross signal = "+marketOrder.PositionTypeToString(signal)+
"\n MA validation = "+marketOrder.PositionTypeToString(validation)+
"\n");
}
else
{
Comment("EA trading schedule not used. Trading is enabled."+
"\n MA1 [2]: "+DoubleToString(MA1[2],_Digits)+" [1]: "+DoubleToString(MA1[1],_Digits)+
"\n MA2 [2]: "+DoubleToString(MA2[2],_Digits)+" [1]: "+DoubleToString(MA2[1],_Digits)+
"\n MA cross signal = "+marketOrder.PositionTypeToString(signal)+
"\n MA validation = "+marketOrder.PositionTypeToString(validation)+
"\n");
}
if(signal == POSITION_TYPE_BUY)
{
if(marketOrder.IsOpen(currentTicket,_Symbol,POSITION_TYPE_SELL,MagicNumber))
{
if(currentTicket > 0 && ForceSR)
{
if(IsTradeDirectionValid(POSITION_TYPE_SELL))
{
PrintFormat("Reversing %s position on Stop&Reverse condition (ticket:%d)", _Symbol, currentTicket);
marketOrder.Reverse(currentTicket,Lots,StopLoss,TakeProfit);
}
}
return;
}
else if(!marketOrder.IsOpen(_Symbol,POSITION_TYPE_BUY,MagicNumber))
{
if(IsTradeDirectionValid(POSITION_TYPE_BUY))
marketOrder.Long(_Symbol,Lots,StopLoss,TakeProfit);
return;
}
}
else if(signal == POSITION_TYPE_SELL)
{
if(marketOrder.IsOpen(currentTicket,_Symbol,POSITION_TYPE_BUY,MagicNumber))
{
if(currentTicket > 0 && ForceSR)
{
if(IsTradeDirectionValid(POSITION_TYPE_SELL))
{
PrintFormat("Reversing %s position on Stop&Reverse condition (ticket:%d)", _Symbol, currentTicket);
marketOrder.Reverse(currentTicket,Lots,StopLoss,TakeProfit);
}
}
return;
}
else if(!marketOrder.IsOpen(_Symbol,POSITION_TYPE_SELL,MagicNumber))
{
if(IsTradeDirectionValid(POSITION_TYPE_SELL))
marketOrder.Short(_Symbol,Lots,StopLoss,TakeProfit);
return;
}
}
//
// Handling of crosses inside price gap
// Condition: No valid cross signal, but MA validation changed
//
if(marketOrder.IsOpen(currentTicket,currentPositionType,_Symbol,MagicNumber))
{
if(currentTicket > 0)
{
if((currentPositionType != validation) && (validation != POSITION_TYPE_NONE) && signal == POSITION_TYPE_NONE)
{
if(ReverseOnMACrossInsideGap)
{
// reverse position on signal change inside gap.
PrintFormat("Reversing %s position on signal change inside gap (ticket:%d)", _Symbol, currentTicket);
marketOrder.Reverse(currentTicket,Lots,StopLoss,TakeProfit);
}
else
{
// close position on signal change inside gap.
PrintFormat("Closing %s position on signal change inside gap (ticket:%d)", _Symbol, currentTicket);
marketOrder.Close(currentTicket);
}
}
}
}
}
}
}
//
// Trade direction validation (Is it OK to trade in the given direction?)
//
bool IsTradeDirectionValid(ENUM_POSITION_TYPE signalDirection)
{
if(ValidTradeDirection == TRADE_DIRECTION_ALL)
return true;
if(signalDirection == POSITION_TYPE_BUY && ValidTradeDirection == TRADE_DIRECTION_BUY)
return true;
else if(signalDirection == POSITION_TYPE_SELL && ValidTradeDirection == TRADE_DIRECTION_SELL)
return true;
else
return false;
}
//
// MA cross logic
//
ENUM_POSITION_TYPE MovingAverageCross()
{
if(2 < numberOfBars-1)
{
Alert("Invalid number of MA readings defined! MA Cross cannot be determined.");
return POSITION_TYPE_NONE;
}
if((MA2[1] > MA1[1]) && (MA2[2] < MA1[2]))
return POSITION_TYPE_SELL;
else if((MA2[1] < MA1[1]) && (MA2[2] > MA1[2]))
return POSITION_TYPE_BUY;
else
return POSITION_TYPE_NONE;
}
ENUM_POSITION_TYPE MovingAverageValidation()
{
if(MA2[1] > MA1[1])
return POSITION_TYPE_SELL;
else if(MA2[1] < MA1[1])
return POSITION_TYPE_BUY;
return POSITION_TYPE_NONE;
}
Binary file not shown.
+439
View File
@@ -0,0 +1,439 @@
#property copyright "Copyright 2017-2021, Artur Zas"
// GNU General Public License v3.0 -> https://github.com/9nix6/Median-and-Turbo-Renko-indicator-bundle/blob/master/LICENSE
#property link "https://www.az-invest.eu"
#property version "1.09"
#property description "Example EA: Trading based on moving average & price crossover."
#property description "MA1 needs to be enabled on the inicator creating the chart."
//#define ULTIMATE_RENKO_LICENSE // uncomment when used on Ultimate Renko chart from https://www.az-invest.eu/ultimate-renko-indicator-generator-for-metatrader-5
//#define VOLUMECHART_LICENSE // uncomment when used on a Tick & Volume bar chart from https://www.az-invest.eu/Tick-chart-and-volume-chart-for-mt5
//#define RANGEBAR_LICENSE // uncomment when used on a Tick & Volume bar chart from https://www.az-invest.eu/rangebars-for-metatrader-5
//#define SECONDSCHART_LICENSE // uncomment when used on a Seconds TF bar chart from https://www.az-invest.eu/seconds-timeframe-chart-for-metatrader-5
//#define LINEBREAKCHART_LICENSE // uncomment when used on a Line Break chart from https://www.az-invest.eu
//
// Uncomment only ONE of the 5 directives listed below and recompile
// -----------------------------------------------------------------
//
#define EA_ON_RANGE_BARS // Use EA on RangeBar chart
//#define EA_ON_RENKO // Use EA on Renko charts
//#define EA_ON_XTICK_CHART // Use EA on XTick Chart (obsolete)
//#define EA_ON_TICK_VOLUME_CHART // Use EA on Tick & Volume Bar Chart
//#define EA_ON_SECONDS_CHART // Use EA on Seconds Interval chart
//#define EA_ON_LINEBREAK_CHART // Use EA on LineBreak charts
//#define DEVELOPER_VERSION // used when I develop ;) should always be commented out
// Uncomment the directive below and recompile if EA is used with P-Renko BR Ultimate
// ----------------------------------------------------------------------------------
//
// #define P_RENKO_BR_PRO // Use in P-Renko BR Ultimate version
//
// Uncomment the directive below and recompile for use in a backtest only
// ----------------------------------------------------------------------
//
// #define SHOW_INDICATOR_INPUTS
// Include all needed files
#ifdef EA_ON_RANGE_BARS
#include <AZ-INVEST/SDK/RangeBars.mqh>
RangeBars *customBars = NULL;
#endif
#ifdef EA_ON_RENKO
#include <AZ-INVEST/SDK/MedianRenko.mqh>
MedianRenko *customBars = NULL;
#endif
#ifdef EA_ON_XTICK_CHART
#include <AZ-INVEST/SDK/TickChart.mqh>
TickChart *customBars = NULL;
#endif
#ifdef EA_ON_TICK_VOLUME_CHART
#include <AZ-INVEST/SDK/VolumeBarChart.mqh>
TickChart *customBars = NULL;
#endif
#ifdef EA_ON_SECONDS_CHART
#include <AZ-INVEST/SDK/SecondsChart.mqh>
SecondsChart *customBars = NULL;
#endif
#ifdef EA_ON_LINEBREAK_CHART
#include <AZ-INVEST/SDK/LineBreakChart.mqh>
LineBreakChart *customBars = NULL;
#endif
#include <AZ-INVEST/SDK/TimeControl.mqh>
#include <AZ-INVEST/SDK/TradeFunctions.mqh>
enum ENUM_TRADE_DIRECTION
{
TRADE_DIRECTION_BUY = POSITION_TYPE_BUY, // Buy
TRADE_DIRECTION_SELL = POSITION_TYPE_SELL, // Sell
TRADE_DIRECTION_ALL = 1000, // Buy & Sell
};
#ifdef SHOW_INDICATOR_INPUTS
input group "EA parameters"
#endif
input double Lots = 0.1; // Traded lots
input uint StopLoss = 0; // Stop Loss
input uint TakeProfit = 0; // Take profit
input int ConfirmationBars = 1; // Signal confirmation bars
input int PrevSignalBars = 1; // Prev signal confirmation bars
input ENUM_TRADE_DIRECTION ValidTradeDirection = TRADE_DIRECTION_ALL; // Valid trading type
input bool CloseTradeOnSignalChange = true; // Close trade on signal change
input bool ForceSR = false; // Force Stop & Reverse
input bool CloseTradeAfterTradingHours = true; // Close trade after trading hours
input ulong DeviationPoints = 0; // Maximum defiation (in points)
input double ManualTickSize = 0.000; // Tick Size (0 = auto detect)
input string Start="9:00"; // Start trading at
input string End="17:55"; // End trading at
input ulong MagicNumber=8888; // Assign trade ID
input int NumberOfRetries = 50; // Maximum number of retries
input int BusyTimeout_ms = 1000; // Wait [ms] before retry on bussy errors
input int RequoteTimeout_ms = 250; // Wait [ms] before retry on requotes
// Global data buffers
MqlRates RateInfo[]; // Buffer for custom price bars
double MA1[]; // Buffer for moving average 1
// Read 4 rates MA1 values starting from current (uncompleted) bar
int startAtBar = 0;
int numberOfBars;
int _confirmationBars;
int _prevSignalBars;
// EA variables
CMarketOrder *marketOrder;
CTimeControl *timeControl;
ulong currentTicket;
ENUM_POSITION_TYPE currentPositionType;
ENUM_POSITION_TYPE signal;
ENUM_POSITION_TYPE validation;
#ifdef EA_ON_RANGE_BARS
static int _MA1 = RANGEBAR_MA1;
static int _MA2 = RANGEBAR_MA2;
#endif
#ifdef EA_ON_RENKO
static int _MA1 = RENKO_MA1;
static int _MA2 = RENKO_MA2;
#endif
#ifdef EA_ON_XTICK_CHART
static int _MA1 = TICKCHART_MA1;
static int _MA2 = TICKCHART_MA2;
#endif
#ifdef EA_ON_TICK_VOLUME_CHART
static int _MA1 = VOLUMECHART_MA1;
static int _MA2 = VOLUMECHART_MA2;
#endif
#ifdef EA_ON_SECONDS_CHART
static int _MA1 = SECONDS_MA1;
static int _MA2 = SECONDS_MA2;
#endif
#ifdef EA_ON_LINEBREAK_CHART
static int _MA1 = LINEBREAK_MA1;
static int _MA2 = LINEBREAK_MA2;
#endif
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
if(customBars == NULL)
{
#ifdef EA_ON_RANGE_BARS
customBars = new RangeBars(MQLInfoInteger((int)MQL5_TESTING) ? false : true);
#endif
#ifdef EA_ON_RENKO
customBars = new MedianRenko(MQLInfoInteger((int)MQL5_TESTING) ? false : true);
#endif
#ifdef EA_ON_XTICK_CHART
customBars = new TickChart(MQLInfoInteger((int)MQL5_TESTING) ? false : true);
#endif
#ifdef EA_ON_TICK_VOLUME_CHART
customBars = new TickChart(MQLInfoInteger((int)MQL5_TESTING) ? false : true);
#endif
#ifdef EA_ON_SECONDS_CHART
customBars = new SecondsChart(MQLInfoInteger((int)MQL5_TESTING) ? false : true);
#endif
#ifdef EA_ON_LINEBREAK_CHART
customBars = new LineBreakChart(MQLInfoInteger((int)MQL5_TESTING) ? false : true);
#endif
}
customBars.Init();
signal = POSITION_TYPE_NONE;
_confirmationBars = (ConfirmationBars < 1) ? 1 : ConfirmationBars;
_prevSignalBars = (PrevSignalBars < 1) ? 1 : PrevSignalBars;
numberOfBars = _confirmationBars + _prevSignalBars + 1;
CMarketOrderParameters params;
{
params.m_async_mode = false;
params.m_magic = MagicNumber;
params.m_deviation = DeviationPoints;
params.m_type_filling = ORDER_FILLING_FOK;
params.numberOfRetries = NumberOfRetries;
params.busyTimeout_ms = BusyTimeout_ms;
params.requoteTimeout_ms = RequoteTimeout_ms;
}
marketOrder = new CMarketOrder(params);
if(timeControl == NULL)
{
timeControl = new CTimeControl();
}
timeControl.SetValidTraingHours(Start,End);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
customBars.Deinit();
// delete TimeControl class
if(timeControl != NULL)
{
delete timeControl;
timeControl = NULL;
}
// delete MarketOrder class
if(marketOrder != NULL)
{
delete marketOrder;
marketOrder = NULL;
}
// delete MedianRenko class
if(customBars != NULL)
{
delete customBars;
customBars = NULL;
}
Comment("");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
if(marketOrder == NULL)
return;
if(customBars.IsNewBar())
{
if(timeControl.IsScheduleEnabled())
{
Comment("EA trading schedule ON ("+Start+" to "+End+") | trading enabled = "+(string)timeControl.IsTradingTimeValid());
}
else
{
Comment("EA trading schedule OFF");
}
if(!timeControl.IsTradingTimeValid())
{
if(marketOrder.IsOpen(currentTicket,_Symbol,MagicNumber))
{
if(currentTicket > 0 && CloseTradeAfterTradingHours)
{
// close position outside of trading hours
marketOrder.Close(currentTicket);
}
}
return;
}
//
// Get MqlRateInfo & moving average values for current, last completed bar and the bar before that...
//
if(!customBars.GetMqlRates(RateInfo,startAtBar,numberOfBars))
{
Print("Error getting MqlRates for custom chart");
}
else if(!customBars.GetMA(_MA1, MA1, startAtBar, numberOfBars))
{
Print("Error getting values from MA1 - please enable MA1 on chart");
}
else
{
signal = PriceAndMovingAverageCross(_confirmationBars, _prevSignalBars);
if(timeControl.IsScheduleEnabled())
{
Comment("EA trading schedule ("+Start+" to "+End+") | trading enabled = "+(string)timeControl.IsTradingTimeValid()+
"\n MA_1 [2]: "+DoubleToString(MA1[2],_Digits)+" [1]: "+DoubleToString(MA1[1],_Digits)+
"\n Close[2]: "+DoubleToString(RateInfo[2].close,_Digits)+" [1]: "+DoubleToString(RateInfo[1].close,_Digits)+
"\n Price & MA cross signal = "+marketOrder.PositionTypeToString(signal)+
"\n");
}
else
{
Comment("EA trading schedule not used. Trading is enabled."+
"\n MA_1 [2]: "+DoubleToString(MA1[2],_Digits)+" [1]: "+DoubleToString(MA1[1],_Digits)+
"\n Close[2]: "+DoubleToString(RateInfo[2].close,_Digits)+" [1]: "+DoubleToString(RateInfo[1].close,_Digits)+
"\n Price & MA cross signal = "+marketOrder.PositionTypeToString(signal)+
"\n");
}
if(signal == POSITION_TYPE_BUY)
{
if(marketOrder.IsOpen(currentTicket,_Symbol,POSITION_TYPE_SELL,MagicNumber))
{
if(currentTicket > 0 && ForceSR)
{
if(IsTradeDirectionValid(POSITION_TYPE_SELL))
{
PrintFormat("Reversing %s position on Stop&Reverse condition (ticket:%d)", _Symbol, currentTicket);
marketOrder.Reverse(currentTicket,Lots,StopLoss,TakeProfit);
}
}
else if(currentTicket > 0)
{
// close trade on signal change
if(CloseTradeOnSignalChange)
{
PrintFormat("Closing %s position on signal change (ticket:%d)", _Symbol, currentTicket);
marketOrder.Close(currentTicket);
}
}
return;
}
if(!marketOrder.IsOpen(_Symbol,POSITION_TYPE_BUY,MagicNumber))
{
if(IsTradeDirectionValid(POSITION_TYPE_BUY))
marketOrder.Long(_Symbol,Lots,StopLoss,TakeProfit);
return;
}
}
else if(signal == POSITION_TYPE_SELL)
{
if(marketOrder.IsOpen(currentTicket,_Symbol,POSITION_TYPE_BUY,MagicNumber))
{
if(currentTicket > 0 && ForceSR)
{
if(IsTradeDirectionValid(POSITION_TYPE_BUY))
{
PrintFormat("Reversing %s position on Stop&Reverse condition (ticket:%d)", _Symbol, currentTicket);
marketOrder.Reverse(currentTicket,Lots,StopLoss,TakeProfit);
}
}
else if(currentTicket > 0)
{
// close trade on signal change
if(CloseTradeOnSignalChange)
{
PrintFormat("Closing %s position on signal change (ticket:%d)", _Symbol, currentTicket);
marketOrder.Close(currentTicket);
}
}
return;
}
if(!marketOrder.IsOpen(_Symbol,POSITION_TYPE_SELL,MagicNumber))
{
if(IsTradeDirectionValid(POSITION_TYPE_SELL))
marketOrder.Short(_Symbol,Lots,StopLoss,TakeProfit);
return;
}
}
}
}
}
//
// Trade direction validation (Is it OK to trade in the given direction?)
//
bool IsTradeDirectionValid(ENUM_POSITION_TYPE signalDirection)
{
if(ValidTradeDirection == TRADE_DIRECTION_ALL)
return true;
if(signalDirection == POSITION_TYPE_BUY && ValidTradeDirection == TRADE_DIRECTION_BUY)
return true;
else if(signalDirection == POSITION_TYPE_SELL && ValidTradeDirection == TRADE_DIRECTION_SELL)
return true;
else
return false;
}
//
// Price & MA cross logic
//
ENUM_POSITION_TYPE PriceAndMovingAverageCross(int confirmationBars, int prevSignalBars)
{
if(numberOfBars < confirmationBars+1)
{
Alert("Invalid number of MqlRates and MA readings defined! Crossover cannot be determined.");
return POSITION_TYPE_NONE;
}
bool confirmedSell = true;
bool confirmedBuy = true;
// check trailing bar for confirmation of previous signal
for(int i=(confirmationBars+1); i<=(confirmationBars+prevSignalBars); i++)
{
if(RateInfo[i].close > MA1[i])
{
confirmedBuy = false;
}
else if(RateInfo[i].close < MA1[i])
{
confirmedSell = false;
}
}
// check confirmation bars for current signal
for(int i=1; i<=confirmationBars; i++)
{
if(RateInfo[i].close == MA1[i])
{
confirmedSell = false;
confirmedBuy = false;
}
else if(RateInfo[i].close < MA1[i])
{
confirmedBuy = false;
}
else if(RateInfo[i].close > MA1[i])
{
confirmedSell = false;
}
}
// signal aggregate
if(confirmedSell)
return POSITION_TYPE_SELL;
else if(confirmedBuy)
return POSITION_TYPE_BUY;
else
return POSITION_TYPE_NONE;
}
Binary file not shown.
+38 -60
View File
@@ -1,10 +1,14 @@
#property copyright "Copyright 2017, AZ-iNVEST"
#property link "http://www.az-invest.eu"
#property version "2.05"
#property copyright "Copyright 2017-2020, Level Up Software"
#property link "https://www.az-invest.eu"
#property version "2.07"
#property description "Example EA showing the way to use the RangeBars class defined in RangeBars.mqh"
input int InpRSIPeriod = 14; // RSI period
//#define DEVELOPER_VERSION // used when I develop ;) should always be commented out
//
// SHOW_INDICATOR_INPUTS *NEEDS* to be defined, if the EA needs to be *tested in MT5's backtester*
// SHOW_INDICATOR_INPUTS *NEEDS* to be defined, if the sEA needs to be *tested in MT5's backtester*
// -------------------------------------------------------------------------------------------------
// Using '#define SHOW_INDICATOR_INPUTS' will show the RangeBars indicator's inputs
// NOT using the '#define SHOW_INDICATOR_INPUTS' statement will read the settigns a chart with
@@ -20,21 +24,21 @@
#include <AZ-INVEST/SDK/RangeBars.mqh>
//
// To use the RangeBars indicator in your EA you need do instantiate the indicator class (RangeBars)
// and call the Init() method in your EA's OnInit() function.
// Don't forget to release the indicator when you're done by calling the Deinit() method.
// Example shown in OnInit & OnDeinit functions below:
// and call the Init() and Deinit() methods in your EA's OnInit() and OnDeinit() functions.
// Example shown below
//
RangeBars * rangeBars;
RangeBars *rangeBars = NULL;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
rangeBars = new RangeBars();
if(rangeBars == NULL)
return(INIT_FAILED);
{
rangeBars = new RangeBars(MQLInfoInteger((int)MQL5_TESTING) ? false : true);
}
rangeBars.Init();
if(rangeBars.GetHandle() == INVALID_HANDLE)
@@ -55,6 +59,7 @@ void OnDeinit(const int reason)
{
rangeBars.Deinit();
delete rangeBars;
rangeBars = NULL;
}
//
@@ -70,8 +75,22 @@ void OnDeinit(const int reason)
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
int rsiHandle = INVALID_HANDLE; // Handle for the external RSI indicator
void OnTick()
{
//
// Initialize all additional indicators here! (not in the OnInit() function).
// Otherwise they will not work in the backtest.
// When backtesting please select the "Daily" timeframe.
//
if(rsiHandle == INVALID_HANDLE)
{
rsiHandle = iCustom(_Symbol, _Period, "RangeBars\\RangeBars_RSI", InpRSIPeriod, true);
}
//
// It is considered good trading & EA coding practice to perform calculations
// when a new bar is fully formed.
@@ -96,7 +115,7 @@ void OnTick()
double MA1[]; // array to be filled by values of the first moving average
double MA2[]; // array to be filled by values of the second moving average
if(rangeBars.GetMA1(MA1,startAtBar,numberOfBars) && rangeBars.GetMA1(MA2,startAtBar,numberOfBars))
if(rangeBars.GetMA(RANGEBAR_MA1, MA1, startAtBar, numberOfBars) && rangeBars.GetMA(RANGEBAR_MA2, MA2, startAtBar, numberOfBars))
{
//
// Values are stored in the MA1 and MA2 arrays and are now ready for use
@@ -182,64 +201,23 @@ void OnTick()
}
//
// Getting Donchain channel values is done using the
// GetDonchian(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count)
// method. Example below:
// Getting the values of the channel indicator (Donchain, Bullinger Bands, Keltner or Super Trend) is done using
// GetChannel(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count)
// Example below:
//
double HighArray[]; // This array will store the values of the high band
double MidArray[]; // This array will store the values of the middle band
double LowArray[]; // This array will store the values of the low band
double HighArray[]; // This array will store the values of the channel's high band
double MidArray[]; // This array will store the values of the channel's middle band
double LowArray[]; // This array will store the values of the channel's low band
startAtBar = 1; // get values starting from the last completed bar.
numberOfBars = 20; // gat a total of 20 values (for 20 bars starting from bar 1 (last completed))
if(rangeBars.GetDonchian(HighArray,MidArray,LowArray,startAtBar,numberOfBars))
if(rangeBars.GetChannel(HighArray,MidArray,LowArray,startAtBar,numberOfBars))
{
//
// Apply your Donchian channel logic here...
//
}
//
// Getting Bollinger Bands values is done using the
// GetBollingerBands(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count)
// method. Example below:
//
// HighArray[] array will store the values of the high band
// MidArray[] array will store the values of the middle band
// LowArray[] array will store the values of the low band
startAtBar = 1; // get values starting from the last completed bar.
numberOfBars = 10; // gat a total of 10 values (for 10 bars starting from bar 1 (last completed))
if(rangeBars.GetBollingerBands(HighArray,MidArray,LowArray,startAtBar,numberOfBars))
{
//
// Apply your Bollinger Bands logic here...
// Apply your logic here...
//
}
//
// Getting SuperTrend values is done using the
// GetSuperTrend(double &SuperTrendHighArray[], double &SuperTrendArray[], double &SuperTrendLowArray[], int start, int count)
// method. Example below:
//
// HighArray[] array will store the values of the high SuperTrend line
// MidArray[] array will store the values of the SuperTrend value
// LowArray[] array will store the values of the low SuperTrend line
startAtBar = 1; // get values starting from the last completed bar.
numberOfBars = 3; // gat a total of 3 values (for 3 bars starting from bar 1 (last completed))
if(rangeBars.GetSuperTrend(HighArray,MidArray,LowArray,startAtBar,numberOfBars))
{
//
// Apply your SuperTrend logic here...
//
}
}
}
Binary file not shown.
+26 -14
View File
@@ -1,6 +1,6 @@
#property copyright "Copyright 2017, AZ-iNVEST"
#property link "http://www.az-invest.eu"
#property version "1.00"
#property copyright "Copyright 2017-2020, Level Up Software"
#property link "https://www.az-invest.eu"
#property version "1.11"
#property description "Example EA: Trading based on RangeBars SuperTrend signals."
#property description "One trade at a time. Each trade has TP & SL"
@@ -10,6 +10,8 @@
#include <AZ-INVEST/SDK/TradeFunctions.mqh>
//#define DEVELOPER_VERSION // used when I develop ;) should always be commented out
//
// Inputs
//
@@ -48,22 +50,22 @@ ulong currentTicket;
#include <AZ-INVEST/SDK/RangeBars.mqh>
//
// To use the RangeBars indicator in your EA you need do instantiate the indicator class (RangeBars)
// and call the Init() method in your EA's OnInit() function.
// Don't forget to release the indicator when you're done by calling the Deinit() method.
// Example shown in OnInit & OnDeinit functions below:
// and call the Init() and Deinit() methods in your EA's OnInit() and OnDeinit() functions.
// Example shown below
//
RangeBars * rangeBars;
CMarketOrder * marketOrder;
RangeBars *rangeBars = NULL;
CMarketOrder *marketOrder = NULL;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
rangeBars = new RangeBars();
if(rangeBars == NULL)
return(INIT_FAILED);
{
rangeBars = new RangeBars(MQLInfoInteger((int)MQL5_TESTING) ? false : true);
}
rangeBars.Init();
if(rangeBars.GetHandle() == INVALID_HANDLE)
@@ -84,8 +86,12 @@ int OnInit()
params.busyTimeout_ms = InpBusyTimeout_ms;
params.requoteTimeout_ms = InpRequoteTimeout_ms;
}
marketOrder = new CMarketOrder(params);
if(marketOrder == NULL)
{
marketOrder = new CMarketOrder(params);
}
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
@@ -93,10 +99,15 @@ int OnInit()
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//
// delete RanegBars class
//
if(rangeBars != NULL)
{
rangeBars.Deinit();
delete rangeBars;
rangeBars = NULL;
}
//
@@ -106,6 +117,7 @@ void OnDeinit(const int reason)
if(marketOrder != NULL)
{
delete marketOrder;
marketOrder = NULL;
}
}
@@ -130,7 +142,7 @@ void OnTick()
//
// Getting SuperTrend values is done using the
// GetSuperTrend(double &SuperTrendHighArray[], double &SuperTrendArray[], double &SuperTrendLowArray[], int start, int count)
// GetChannel(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count)
// method. Example below:
//
@@ -141,7 +153,7 @@ void OnTick()
int startAtBar = 1; // get values starting from the last completed bar.
int numberOfBars = 2; // gat a total of 3 values (for 3 bars starting from bar 1 (last completed))
if(rangeBars.GetSuperTrend(HighArray,MidArray,LowArray,startAtBar,numberOfBars))
if(rangeBars.GetChannel(HighArray,MidArray,LowArray,startAtBar,numberOfBars))
{
//
// Read signal bar's time for optional debug log
+52
View File
@@ -0,0 +1,52 @@
//#define DEVELOPER_VERSION
//#define DISPLAY_DEBUG_MSG
#define MQL5_MARKET_VERSION
//#define P_RENKO_BR_PRO
//#define ULTIMATE_RENKO_LICENSE
#define RANGEBAR_LICENSE
//#define SECONDSCHART_LICENSE
//#define TICKCHART_LICENSE (obsolete)
//#define VOLUMECHART_LICENSE
//#define LINEBREAKCHART_LICENSE
#ifdef P_RENKO_BR_PRO
#include <AZ-INVEST/SDK/MedianRenkoIndicator.mqh>
#define AZINVEST_CCI MedianRenkoIndicator
#endif
#ifdef TICKCHART_LICENSE
#include <AZ-INVEST/SDK/TickChartIndicator.mqh>
#define AZINVEST_CCI TickChartIndicator
#endif
#ifdef RANGEBAR_LICENSE
#include <AZ-INVEST/SDK/RangeBarIndicator.mqh>
#define AZINVEST_CCI RangeBarIndicator
#endif
#ifdef ULTIMATE_RENKO_LICENSE
#include <AZ-INVEST/SDK/MedianRenkoIndicator.mqh>
#define AZINVEST_CCI MedianRenkoIndicator
#endif
#ifdef SECONDSCHART_LICENSE
#include <AZ-INVEST/SDK/SecondsChartIndicator.mqh>
#define AZINVEST_CCI SecondsChartIndicator
#endif
#ifdef VOLUMECHART_LICENSE
#include <AZ-INVEST/SDK/VolumeChartIndicator.mqh>
#define AZINVEST_CCI VolumeChartIndicator
#endif
#ifdef LINEBREAKCHART_LICENSE
#include <AZ-INVEST/SDK/LineBreakChartIndicator.mqh>
#define AZINVEST_CCI LineBreakChartIndicator
#endif
#ifdef AZINVEST_CCI
AZINVEST_CCI customChartIndicator;
#endif
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+53
View File
@@ -0,0 +1,53 @@
//
// Copyright 2017-2018, Artur Zas
// https://www.az-invest.eu
// https://www.mql5.com/en/users/arturz
//
// Normalizing functions
//
double NormalizeLots(string symbol, double InputLots)
{
double lotsMin = SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
double lotsMax = SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
// int lotsDigits = (int) - MathLog10(SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP));
int lotsDigits = (int)MathAbs(MathLog10(SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP)));
if(InputLots < lotsMin)
InputLots = lotsMin;
if(InputLots > lotsMax)
InputLots = lotsMax;
return NormalizeDouble(InputLots, lotsDigits);
}
double VtcNormalizeLots(string symbol, double lotsToNormalize)
{
double lotsMin = SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
double lotsMax = SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
double lotsStep = SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
if (lotsToNormalize == 0)
return lotsMin;
int a = (int)(lotsToNormalize / lotsStep);
double normalizedLots = a * lotsStep;
if(normalizedLots < lotsMin)
normalizedLots = lotsMin;
if(normalizedLots > lotsMax)
normalizedLots = lotsMax;
return normalizedLots;
}
double NormalizePrice(string symbol, double price, double tick = 0)
{
double _tick = tick ? tick : SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE);
int _digits = (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
if (tick)
return NormalizeDouble(MathRound(price/_tick)*_tick,_digits);
else
return NormalizeDouble(price,_digits);
}
+83
View File
@@ -0,0 +1,83 @@
// RSI on Buffer
int RsiOnBuffer(const int rates_total,const int prev_calculated,const int begin,
const int period,const double& price[],double& rsiBuffer[], double &posBuffer[], double &negBuffer[])
{
int i, pos;
double diff;
//--- check for data
if(period<=1 || rates_total-begin<period) return(0);
//--- save as_series flags
bool as_series_price=ArrayGetAsSeries(price);
bool as_series_rsibuffer=ArrayGetAsSeries(rsiBuffer);
bool as_series_posbuffer=ArrayGetAsSeries(posBuffer);
bool as_series_negbuffer=ArrayGetAsSeries(negBuffer);
if(as_series_price) ArraySetAsSeries(price,false);
if(as_series_rsibuffer) ArraySetAsSeries(rsiBuffer,false);
if(as_series_posbuffer) ArraySetAsSeries(posBuffer,false);
if(as_series_negbuffer) ArraySetAsSeries(negBuffer,false);
//--- preliminary calculations
pos=prev_calculated-1;
if(pos<=period)
{
//--- first RSIPeriod values of the indicator are not calculated
rsiBuffer[0]=0.0;
posBuffer[0]=0.0;
negBuffer[0]=0.0;
double sump=0.0;
double sumn=0.0;
for(i=1; i<=period; i++)
{
rsiBuffer[i]=0.0;
posBuffer[i]=0.0;
negBuffer[i]=0.0;
diff=price[i]-price[i-1];
if(diff>0)
sump+=diff;
else
sumn-=diff;
}
//--- calculate first visible value
posBuffer[period]=sump/period;
negBuffer[period]=sumn/period;
if(negBuffer[period]!=0.0)
rsiBuffer[period]=100.0-(100.0/(1.0+posBuffer[period]/negBuffer[period]));
else
{
if(posBuffer[period]!=0.0)
rsiBuffer[period]=100.0;
else
rsiBuffer[period]=50.0;
}
//--- prepare the position value for main calculation
pos=period+1;
}
//--- the main loop of calculations
for(i=pos; i<rates_total && !IsStopped(); i++)
{
diff=price[i]-price[i-1];
posBuffer[i]=(posBuffer[i-1]*(period-1)+(diff>0.0?diff:0.0))/period;
negBuffer[i]=(negBuffer[i-1]*(period-1)+(diff<0.0?-diff:0.0))/period;
if(negBuffer[i]!=0.0)
rsiBuffer[i]=100.0-100.0/(1+posBuffer[i]/negBuffer[i]);
else
{
if(posBuffer[i]!=0.0)
rsiBuffer[i]=100.0;
else
rsiBuffer[i]=50.0;
}
}
//--- restore as_series flags
if(as_series_price) ArraySetAsSeries(price,true);
if(as_series_rsibuffer) ArraySetAsSeries(rsiBuffer,true);
if(as_series_posbuffer) ArraySetAsSeries(posBuffer,true);
if(as_series_negbuffer) ArraySetAsSeries(negBuffer,true);
//---
return(rates_total);
}
//+------------------------------------------------------------------+
@@ -0,0 +1,120 @@
#include <AZ-INVEST/SDK/CommonSettings.mqh>
#ifdef DEVELOPER_VERSION
#define CUSTOM_CHART_NAME "RangeBars_TEST"
#else
#define CUSTOM_CHART_NAME "Range Bars"
#endif
//
// Tick chart specific settings
//
#ifdef SHOW_INDICATOR_INPUTS
#ifdef MQL5_MARKET_DEMO // hardcoded values
int barSizeInTicks = 180; // Range bar size (in ticks)
ENUM_BOOL atrEnabled = false; // Enable ATR based bar size calculation
ENUM_TIMEFRAMES atrTimeFrame = PERIOD_D1; // Use ATR period
int atrPeriod = 14; // ATR period
int atrPercentage = 10; // Use percentage of ATR
int showNumberOfDays = 7; // Show history for number of days
ENUM_BOOL resetOpenOnNewTradingDay = true; // Synchronize first bar's open on new day
#else // user defined settings
input int barSizeInTicks = 100; // Range bar size (in ticks)
input int showNumberOfDays = 5; // Show history for number of days
input group "### ATR based bar size calculation"
input ENUM_BOOL atrEnabled = false; // Enable ATR based bar size calculation
input ENUM_TIMEFRAMES atrTimeFrame = PERIOD_D1; // Use ATR period
input int atrPeriod = 14; // ATR period
input int atrPercentage = 10; // Use percentage of ATR
input group "### Chart synchronization"
input ENUM_BOOL resetOpenOnNewTradingDay = true; // Synchronize first bar's open on new day
#endif
#else // don't SHOW_INDICATOR_INPUTS
int barSizeInTicks = 180; // Range bar size (in ticks)
ENUM_BOOL atrEnabled = false; // Enable ATR based bar size calculation
ENUM_TIMEFRAMES atrTimeFrame = PERIOD_D1; // Use ATR period
int atrPeriod = 14; // ATR period
int atrPercentage = 10; // Use percentage of ATR
int showNumberOfDays = 7; // Show history for number of days
ENUM_BOOL resetOpenOnNewTradingDay = true; // Synchronize first bar's open on new day
#endif
//
// Remaining settings are located in the include file below.
// These are common for all custom charts
//
#include <az-invest/sdk/CustomChartSettingsBase.mqh>
struct RANGEBAR_SETTINGS
{
int barSizeInTicks;
ENUM_BOOL atrEnabled;
ENUM_TIMEFRAMES atrTimeFrame;
int atrPeriod;
int atrPercentage;
int showNumberOfDays;
ENUM_BOOL resetOpenOnNewTradingDay;
};
class CRangeBarCustomChartSettigns : public CCustomChartSettingsBase
{
protected:
RANGEBAR_SETTINGS settings;
public:
CRangeBarCustomChartSettigns();
~CRangeBarCustomChartSettigns();
RANGEBAR_SETTINGS GetCustomChartSettings() { return this.settings; };
virtual void SetCustomChartSettings();
virtual string GetSettingsFileName();
virtual uint CustomChartSettingsToFile(int handle);
virtual uint CustomChartSettingsFromFile(int handle);
};
void CRangeBarCustomChartSettigns::CRangeBarCustomChartSettigns()
{
settingsFileName = GetSettingsFileName();
}
void CRangeBarCustomChartSettigns::~CRangeBarCustomChartSettigns()
{
}
string CRangeBarCustomChartSettigns::GetSettingsFileName()
{
return CUSTOM_CHART_NAME+(string)ChartID()+".set";
}
uint CRangeBarCustomChartSettigns::CustomChartSettingsToFile(int file_handle)
{
return FileWriteStruct(file_handle,this.settings);
}
uint CRangeBarCustomChartSettigns::CustomChartSettingsFromFile(int file_handle)
{
return FileReadStruct(file_handle,this.settings);
}
void CRangeBarCustomChartSettigns::SetCustomChartSettings()
{
settings.barSizeInTicks = barSizeInTicks;
settings.atrEnabled = atrEnabled;
settings.atrTimeFrame = atrTimeFrame;
settings.atrPeriod = atrPeriod;
settings.atrPercentage = atrPercentage;
settings.showNumberOfDays = showNumberOfDays;
settings.resetOpenOnNewTradingDay = resetOpenOnNewTradingDay;
}
+205 -78
View File
@@ -1,6 +1,10 @@
#property copyright "Copyright 2017, AZ-iNVEST"
#property copyright "Copyright 2018-2020, Level Up Software"
#property link "http://www.az-invest.eu"
#property version "2.02"
#property version "3.00"
input bool UseOnRangeBarChart = true; // Use this indicator on RangeBar chart
//#define DEVELOPER_VERSION
#include <AZ-INVEST/SDK/RangeBars.mqh>
class RangeBarIndicator
@@ -16,8 +20,12 @@ class RangeBarIndicator
bool useAppliedPrice;
ENUM_APPLIED_PRICE applied_price;
bool firstRun;
bool dataReady;
datetime prevTime;
int prevRatesTotal;
public:
datetime Time[];
@@ -31,8 +39,21 @@ class RangeBarIndicator
double Buy_volume[];
double Sell_volume[];
double BuySell_volume[];
datetime GetTime(int index) { return GetArrayValueDateTime(Time, index); };
double GetOpen(int index) { return GetArrayValueDouble(Open, index); };
double GetLow(int index) { return GetArrayValueDouble(Low, index); };
double GetHigh(int index) { return GetArrayValueDouble(High, index); };
double GetClose(int index) { return GetArrayValueDouble(Close, index); };
double GetPrice(int index) { return GetArrayValueDouble(Price, index); };
long GetTick_volume(int index) { return GetArrayValueLong(Tick_volume, index); };
long GetReal_volume(int index) { return GetArrayValueLong(Real_volume, index); };
double GetBuy_volume(int index) { return GetArrayValueDouble(Buy_volume, index); };
double GetSell_volume(int index) { return GetArrayValueDouble(Sell_volume, index); };
double GetBuySell_volume(int index) { return GetArrayValueDouble(BuySell_volume, index); };
bool IsNewBar;
RangeBarIndicator();
~RangeBarIndicator();
@@ -41,8 +62,11 @@ class RangeBarIndicator
void SetGetVolumeBreakdownFlag() { this.getVolumeBreakdown = true; };
void SetGetTimeFlag() { this.getTime = true; };
bool OnCalculate(const int rates_total,const int prev_calculated, const datetime &_Time[]);
bool OnCalculate(const int _rates_total,const int _prev_calculated, const datetime &_Time[], const double &_Close[]);
void OnDeinit(const int reason);
bool BufferSynchronizationCheck(const double &buffer[]);
int GetPrevCalculated() { return prev_calculated; };
int GetRatesTotal() { return ArraySize(Open); };
void BufferShiftLeft(double &buffer[]);
private:
@@ -64,11 +88,14 @@ class RangeBarIndicator
ENUM_TIMEFRAMES TFMigrate(int tf);
datetime iTime(string symbol,int tf,int index);
double GetArrayValueDouble(double &arr[], int index);
long GetArrayValueLong(long &arr[], int index);
datetime GetArrayValueDateTime(datetime &arr[], int index);
};
RangeBarIndicator::RangeBarIndicator(void)
{
rangeBars = new RangeBars();
rangeBars = new RangeBars(UseOnRangeBarChart);
if(rangeBars != NULL)
rangeBars.Init();
@@ -77,6 +104,9 @@ RangeBarIndicator::RangeBarIndicator(void)
getTime = false;
dataReady = false;
firstRun = true;
prevTime = 0;
prevRatesTotal = 0;
}
RangeBarIndicator::~RangeBarIndicator(void)
@@ -99,6 +129,7 @@ bool RangeBarIndicator::CheckStatus(void)
bool RangeBarIndicator::NeedsReload(void)
{
if(rangeBars.Reload())
{
Print("Chart settings changed - reloading indicator with new settings");
@@ -108,17 +139,13 @@ bool RangeBarIndicator::NeedsReload(void)
return false;
}
bool RangeBarIndicator::OnCalculate(const int _rates_total,const int _prev_calculated, const datetime &_Time[])
bool RangeBarIndicator::OnCalculate(const int _rates_total,const int _prev_calculated, const datetime &_Time[], const double &_Close[])
{
static bool firstRun = true;
if(firstRun)
{
Canvas_IsNewBar(_Time);
Canvas_RatesTotalChangedBy(_rates_total);
IsNewBar = rangeBars.IsNewBar();
firstRun = false;
}
if(!CheckStatus())
@@ -126,10 +153,12 @@ bool RangeBarIndicator::OnCalculate(const int _rates_total,const int _prev_calcu
if(rangeBars != NULL)
delete rangeBars;
rangeBars = new RangeBars();
rangeBars = new RangeBars(UseOnRangeBarChart);
if(rangeBars != NULL)
rangeBars.Init();
Print("CheckStatus block failed");
return false;
}
@@ -145,30 +174,29 @@ bool RangeBarIndicator::OnCalculate(const int _rates_total,const int _prev_calcu
ArraySetAsSeries(this.Sell_volume,false);
ArraySetAsSeries(this.BuySell_volume,false);
bool needsReload = (NeedsReload() || (!this.dataReady));
if(needsReload)
if(firstRun)
{
GetOLHC(0,_rates_total);
firstRun = false;
}
if(NeedsReload() || !this.dataReady)
{
GetOLHC(0,_rates_total);
this.prev_calculated = 0;
firstRun = true;
ChartSetSymbolPeriod(ChartID(), _Symbol, _Period); // try to force reload
return false;
}
/*
if(needsReload || IsNewBar || canvasIsNewTime || (change != 0))
{
Print("reload="+needsReload+", renkoisnewbar="+IsNewBar+", canvasIsNewTime="+canvasIsNewTime+", change="+change);
GetOLHC(0,_rates_total);
this.prev_calculated = ArraySize(this.Open);
return true;
}
*/
}
bool change = Canvas_RatesTotalChangedBy(_rates_total);
if(change != 0)
{
#ifdef DISPLAY_DEBUG_MSG
Print("rates total changed to:"+_rates_total);
#endif
if(change == 1)
{
#ifdef DISPLAY_DEBUG_MSG
@@ -183,7 +211,8 @@ bool RangeBarIndicator::OnCalculate(const int _rates_total,const int _prev_calcu
#endif
GetOLHC(0,_rates_total);
}
this.prev_calculated = 0;//_prev_calculated;
this.prev_calculated = 0;
Canvas_IsNewBar(_Time);
return true;
}
@@ -197,7 +226,7 @@ bool RangeBarIndicator::OnCalculate(const int _rates_total,const int _prev_calcu
{
GetOLHC(0,_rates_total);
this.prev_calculated = 0;
return true; ///////// false
return true;
}
OLHCShiftRight();
@@ -210,9 +239,9 @@ bool RangeBarIndicator::OnCalculate(const int _rates_total,const int _prev_calcu
{
GetOLHC(0,_rates_total);
this.prev_calculated = 0;
firstRun = true;
return true;
}
//
// Only recalculate last bar
@@ -224,6 +253,19 @@ bool RangeBarIndicator::OnCalculate(const int _rates_total,const int _prev_calcu
return true;
}
bool RangeBarIndicator::BufferSynchronizationCheck(const double &buffer[])
{
if(ArraySize(buffer) != ArraySize(Close))
{
#ifdef DEVELOPER_VERSION
Print("### buffers out of synch - refreshing...");
#endif
return false;
}
return true;
}
int RangeBarIndicator::GetOLHC(int start, int count)
{
if((start == 0) && (count == 0) && dataReady)
@@ -241,6 +283,7 @@ int RangeBarIndicator::GetOLHC(int start, int count)
this.Low[last] = tempRates[0].low;
this.High[last] = tempRates[0].high;
this.Close[last] = tempRates[0].close;
if(getTime)
{
this.Time[last] = tempRates[0].time;
@@ -286,10 +329,13 @@ void RangeBarIndicator::OLHCShiftRight()
this.High[i] = this.High[i-1];
this.Low[i] = this.Low[i-1];
this.Close[i] = this.Close[i-1];
if(getTime)
this.Time[i] = this.Time[i-1];
if(useAppliedPrice)
this.Price[i] = this.Price[i-1];
if(getVolumes)
{
this.Tick_volume[i] = this.Tick_volume[i-1];
@@ -310,8 +356,10 @@ void RangeBarIndicator::OLHCShiftRight()
if(getTime)
this.Time[0] = 0;
if(useAppliedPrice)
this.Price[0] = 0.0;
if(getVolumes)
{
this.Tick_volume[0] = 0.0;
@@ -339,8 +387,10 @@ void RangeBarIndicator::OLHCResize()
if(getTime)
ArrayResize(this.Time,count+1);
if(useAppliedPrice)
ArrayResize(this.Price,count+1);
if(getVolumes)
{
ArrayResize(this.Tick_volume,count+1);
@@ -362,8 +412,6 @@ bool RangeBarIndicator::Canvas_IsNewBar(const datetime &_Time[])
datetime now = _Time[0];
ArraySetAsSeries(_Time,false);
static datetime prevTime = 0;
if(prevTime != now)
{
prevTime = now;
@@ -375,8 +423,6 @@ bool RangeBarIndicator::Canvas_IsNewBar(const datetime &_Time[])
bool RangeBarIndicator::Canvas_IsRatesTotalChanged(int ratesTotalNow)
{
static int prevRatesTotal = 0;
if(prevRatesTotal == 0)
prevRatesTotal = ratesTotalNow;
@@ -392,7 +438,6 @@ bool RangeBarIndicator::Canvas_IsRatesTotalChanged(int ratesTotalNow)
int RangeBarIndicator::Canvas_RatesTotalChangedBy(int ratesTotalNow)
{
int changedBy = 0;
static int prevRatesTotal = 0;
if(prevRatesTotal == 0)
prevRatesTotal = ratesTotalNow;
@@ -450,11 +495,11 @@ int RangeBarIndicator::GetOLHCForIndicatorCalc(double &o[],double &l[],double &h
handle = rangeBars.GetHandle();
if(handle == INVALID_HANDLE)
return -1;
int _count = CopyBuffer(handle,RANGEBAR_OPEN,start,count,temp);
if(_count == -1)
int __count = CopyBuffer(handle,RANGEBAR_OPEN,start,count,temp);
if(__count == -1)
{
int errorCode = GetLastError();
if(errorCode == ERR_INDICATOR_DATA_NOT_FOUND)
if(GetLastError() == ERR_INDICATOR_DATA_NOT_FOUND)
{
Print("Waiting for buffers ready flag");
return -2;
@@ -463,95 +508,109 @@ int RangeBarIndicator::GetOLHCForIndicatorCalc(double &o[],double &l[],double &h
return -1;
}
if(_count < count)
if(__count < count)
{
#ifdef DISPLAY_DEBUG_MSG
Print("Fixing offset (req:"+count+" res:"+_count+")");
Print("Fixing offset (req:"+count+" res:"+__count+")");
#endif
ArrayInitialize(o,0x0);
ArrayInitialize(l,0x0);
ArrayInitialize(h,0x0);
ArrayInitialize(c,0x0);
if(getTime)
ArrayInitialize(t,0x0);
if(getVolumes)
{
ArrayInitialize(tickVolume,0x0);
ArrayInitialize(realVolume,0x0);
}
if(getVolumeBreakdown)
{
ArrayInitialize(buyVolume,0x0);
ArrayInitialize(sellVolume,0x0);
ArrayInitialize(buySellVolume,0x0);
}
// less data - indicator requres more
ArrayCopy(o,temp,(count-_count),0);
ArrayCopy(o,temp,(count-__count),0);
if(CopyBuffer(handle,RANGEBAR_LOW,start,_count,temp) == -1)
if(CopyBuffer(handle,RANGEBAR_LOW,start,__count,temp) == -1)
return -1;
ArrayCopy(l,temp,(count-_count),0);
ArrayCopy(l,temp,(count-__count),0);
if(CopyBuffer(handle,RANGEBAR_HIGH,start,_count,temp) == -1)
if(CopyBuffer(handle,RANGEBAR_HIGH,start,__count,temp) == -1)
return -1;
ArrayCopy(h,temp,(count-_count),0);
ArrayCopy(h,temp,(count-__count),0);
if(CopyBuffer(handle,RANGEBAR_CLOSE,start,_count,temp) == -1)
if(CopyBuffer(handle,RANGEBAR_CLOSE,start,__count,temp) == -1)
return -1;
ArrayCopy(c,temp,(count-_count),0);
ArrayCopy(c,temp,(count-__count),0);
if(getTime)
{
if(CopyBuffer(handle,RANGEBAR_BAR_OPEN_TIME,start,_count,temp) == -1)
if(CopyBuffer(handle,RANGEBAR_BAR_OPEN_TIME,start,__count,temp) == -1)
return -1;
ArrayCopy(t,temp,(count-_count),0);
ArrayCopy(t,temp,(count-__count),0);
}
if(getVolumes)
{
if(CopyBuffer(handle,RANGEBAR_TICK_VOLUME,start,_count,temp) == -1)
if(CopyBuffer(handle,RANGEBAR_TICK_VOLUME,start,__count,temp) == -1)
return -1;
ArrayCopy(tickVolume,temp,(count-_count),0);
ArrayCopy(tickVolume,temp,(count-__count),0);
if(CopyBuffer(handle,RANGEBAR_REAL_VOLUME,start,_count,temp) == -1)
if(CopyBuffer(handle,RANGEBAR_REAL_VOLUME,start,__count,temp) == -1)
return -1;
ArrayCopy(realVolume,temp,(count-_count),0);
ArrayCopy(realVolume,temp,(count-__count),0);
}
#ifdef P_RANGEBAR_BR
#ifdef P_RANGEBAR_BR_PRO
if(getVolumeBreakdown)
{
if(CopyBuffer(handle,RANGEBAR_BUY_VOLUME,start,_count,temp) == -1)
if(CopyBuffer(handle,RANGEBAR_BUY_VOLUME,start,__count,temp) == -1)
return -1;
ArrayCopy(buyVolume,temp,(count-_count),0);
ArrayCopy(buyVolume,temp,(count-__count),0);
if(CopyBuffer(handle,RANGEBAR_SELL_VOLUME,start,_count,temp) == -1)
if(CopyBuffer(handle,RANGEBAR_SELL_VOLUME,start,__count,temp) == -1)
return -1;
ArrayCopy(sellVolume,temp,(count-_count),0);
ArrayCopy(sellVolume,temp,(count-__count),0);
if(CopyBuffer(handle,RANGEBAR_BUYSELL_VOLUME,start,_count,temp) == -1)
if(CopyBuffer(handle,RANGEBAR_BUYSELL_VOLUME,start,__count,temp) == -1)
return -1;
ArrayCopy(buySellVolume,temp,(count-_count),0);
ArrayCopy(buySellVolume,temp,(count-__count),0);
}
#else
#endif
#else
if(getVolumeBreakdown)
{
if(CopyBuffer(handle,RANGEBAR_BUY_VOLUME,start,_count,temp) == -1)
if(CopyBuffer(handle,RANGEBAR_BUY_VOLUME,start,__count,temp) == -1)
return -1;
ArrayCopy(buyVolume,temp,(count-_count),0);
ArrayCopy(buyVolume,temp,(count-__count),0);
if(CopyBuffer(handle,RANGEBAR_SELL_VOLUME,start,_count,temp) == -1)
if(CopyBuffer(handle,RANGEBAR_SELL_VOLUME,start,__count,temp) == -1)
return -1;
ArrayCopy(sellVolume,temp,(count-_count),0);
ArrayCopy(sellVolume,temp,(count-__count),0);
if(CopyBuffer(handle,RANGEBAR_BUYSELL_VOLUME,start,_count,temp) == -1)
if(CopyBuffer(handle,RANGEBAR_BUYSELL_VOLUME,start,__count,temp) == -1)
return -1;
ArrayCopy(buySellVolume,temp,(count-_count),0);
ArrayCopy(buySellVolume,temp,(count-__count),0);
}
#endif
@@ -560,10 +619,13 @@ int RangeBarIndicator::GetOLHCForIndicatorCalc(double &o[],double &l[],double &h
{
if(CopyBuffer(handle,RANGEBAR_OPEN,start,count,o) == -1)
return -1;
if(CopyBuffer(handle,RANGEBAR_LOW,start,count,l) == -1)
return -1;
if(CopyBuffer(handle,RANGEBAR_HIGH,start,count,h) == -1)
return -1;
if(CopyBuffer(handle,RANGEBAR_CLOSE,start,count,c) == -1)
return -1;
@@ -571,6 +633,7 @@ int RangeBarIndicator::GetOLHCForIndicatorCalc(double &o[],double &l[],double &h
{
if(CopyBuffer(handle,RANGEBAR_BAR_OPEN_TIME,start,count,temp) == -1)
return -1;
ArrayCopy(t,temp);
}
@@ -578,9 +641,12 @@ int RangeBarIndicator::GetOLHCForIndicatorCalc(double &o[],double &l[],double &h
{
if(CopyBuffer(handle,RANGEBAR_TICK_VOLUME,start,count,temp) == -1)
return -1;
ArrayCopy(tickVolume,temp);
if(CopyBuffer(handle,RANGEBAR_REAL_VOLUME,start,count,temp) == -1)
return -1;
ArrayCopy(realVolume,temp);
}
@@ -590,14 +656,17 @@ int RangeBarIndicator::GetOLHCForIndicatorCalc(double &o[],double &l[],double &h
{
if(CopyBuffer(handle,RANGEBAR_BUY_VOLUME,start,count,temp) == -1)
return -1;
ArrayCopy(buyVolume,temp);
if(CopyBuffer(handle,RANGEBAR_SELL_VOLUME,start,count,temp) == -1)
return -1;
ArrayCopy(sellVolume,temp);
if(CopyBuffer(handle,RANGEBAR_BUYSELL_VOLUME,start,count,temp) == -1)
return -1;
ArrayCopy(buySellVolume,temp);
}
#else
@@ -607,14 +676,17 @@ int RangeBarIndicator::GetOLHCForIndicatorCalc(double &o[],double &l[],double &h
{
if(CopyBuffer(handle,RANGEBAR_BUY_VOLUME,start,count,temp) == -1)
return -1;
ArrayCopy(buyVolume,temp);
if(CopyBuffer(handle,RANGEBAR_SELL_VOLUME,start,count,temp) == -1)
return -1;
ArrayCopy(sellVolume,temp);
if(CopyBuffer(handle,RANGEBAR_BUYSELL_VOLUME,start,count,temp) == -1)
return -1;
ArrayCopy(buySellVolume,temp);
}
#endif
@@ -631,11 +703,11 @@ int RangeBarIndicator::GetOLHCAndApplPriceForIndicatorCalc(double &o[],double &l
{
dataReady = true;
int _count = GetOLHCForIndicatorCalc(o,l,h,c,t,tickVolume,realVolume,buyVolume,sellVolume,buySellVolume,start,count);
if(_count < 0)
int __count = GetOLHCForIndicatorCalc(o,l,h,c,t,tickVolume,realVolume,buyVolume,sellVolume,buySellVolume,start,count);
if(__count < 0)
{
dataReady = false;
return _count;
return __count;
}
if(applied_price == PRICE_CLOSE)
{
@@ -655,22 +727,25 @@ int RangeBarIndicator::GetOLHCAndApplPriceForIndicatorCalc(double &o[],double &l
}
else
{
if(ArrayResize(price,_count) == -1)
if(ArrayResize(price,__count) == -1)
return -1;
for(int i=0; i<_count; i++)
for(int i=0; i<__count; i++)
{
price[i] = CalcAppliedPrice(o[i],l[i],h[i],c[i],_applied_price);
}
}
return _count;
return __count;
}
// TFMigrate:
// https://www.mql5.com/en/forum/2842#comment_39496
//
ENUM_TIMEFRAMES RangeBarIndicator::TFMigrate(int tf)
{
{
switch(tf)
{
{
case 0: return(PERIOD_CURRENT);
case 1: return(PERIOD_M1);
case 5: return(PERIOD_M5);
@@ -698,18 +773,30 @@ ENUM_TIMEFRAMES RangeBarIndicator::TFMigrate(int tf)
case 16408: return(PERIOD_D1);
case 32769: return(PERIOD_W1);
case 49153: return(PERIOD_MN1);
default: return(PERIOD_CURRENT);
}
}
}
}
datetime RangeBarIndicator::iTime(string symbol,int tf,int index)
{
if(index < 0) return(-1);
if(index < 0)
{
return(-1);
}
ENUM_TIMEFRAMES timeframe=TFMigrate(tf);
datetime Arr[];
if(CopyTime(symbol, timeframe, index, 1, Arr)>0)
return(Arr[0]);
else return(-1);
if(CopyTime(symbol, timeframe, index, 1, Arr) > 0)
{
return(Arr[0]);
}
else
{
return(-1);
}
}
//
@@ -764,3 +851,43 @@ void RangeBarIndicator::BufferShiftLeft(double &buffer[])
buffer[i-1] = buffer[i];
}
long RangeBarIndicator::GetArrayValueLong(long &arr[], int index)
{
int size = ArraySize(arr);
if(index < size)
{
return(arr[index]);
}
else
{
return(false);
}
}
double RangeBarIndicator::GetArrayValueDouble(double &arr[], int index)
{
int size = ArraySize(arr);
if(index < size)
{
return(arr[index]);
}
else
{
return(false);
}
}
datetime RangeBarIndicator::GetArrayValueDateTime(datetime &arr[], int index)
{
int size = ArraySize(arr);
if(index < size)
{
return(arr[index]);
}
else
{
return(false);
}
}
-345
View File
@@ -1,345 +0,0 @@
#property copyright "Copyright 2017, AZ-iNVEST"
#property link "http://www.az-invest.eu"
#include <AZ-INVEST/SDK/CommonSettings.mqh>
#define CUSTOM_CHART_NAME "Range Bars"
#ifdef SHOW_INDICATOR_INPUTS
input int barSizeInTicks = 100; // Range bar size (in points)
input ENUM_BOOL atrEnabled = false; // Enable ATR based bar size calculation
ENUM_TIMEFRAMES atrTimeFrame = PERIOD_D1; // Use ATR period
input int atrPeriod = 14; // ATR period
input int atrPercentage = 10; // Use percentage of ATR
ENUM_BOOL useRealVolume = false; // Use real volume ( false for FX )
ENUM_TICK_PRICE_TYPE plotPrice = tickBid; // Build chart using
input int showNumberOfDays = 14; // Show history for number of days
input ENUM_BOOL resetOpenOnNewTradingDay = true; // Synchronize first bar's open on new day
input double TopBottomPaddingPercentage = 0.30; // Use padding top/bottom (0.0 - 1.0)
input ENUM_PIVOT_POINTS showPivots = ppNone; // Show pivot levels
input ENUM_PIVOT_TYPE pivotPointCalculationType = ppHLC3; // Pivot point calculation method
input color RColor = clrDodgerBlue; // Resistance line color
input color PColor = clrGold; // Pivot line color
input color SColor = clrFireBrick; // Support line color
input color PDHColor = clrHotPink; // Previous day's high
input color PDLColor = clrLightSkyBlue; // Previous day's low
input color PDCColor = clrGainsboro; // Previous day's close
input ENUM_BOOL showNextBarLevels = true; // Show current bar's close projections
input color HighThresholdIndicatorColor = clrLime; // Bullish bar projection color
input color LowThresholdIndicatorColor = clrRed; // Bearish bar projection color
input ENUM_BOOL showCurrentBarOpenTime = true; // Display chart info and current bar's open time
input color InfoTextColor = clrWhite; // Current bar's open time info color
input ENUM_BOOL UseSoundSignalOnNewBar = false; // Play sound on new bar
input ENUM_BOOL OnlySignalReversalBars = false; // Only signal reversals
input ENUM_BOOL UseAlertWindow = false; // Display Alert window with new bar info
input ENUM_BOOL SendPushNotifications = false; // Send new bar info push notification to smartphone
input string SoundFileBull = "news.wav"; // Use sound file for bullish bar close
input string SoundFileBear = "timeout.wav"; // Use sound file for bearish bar close
input ENUM_BOOL MA1on = false; // Show first MA
input int MA1period = 20; // 1st MA period
input ENUM_MA_METHOD_EXT MA1method = _MODE_SMA; // 1st MA method
input ENUM_APPLIED_PRICE MA1applyTo = PRICE_CLOSE; // 1st MA apply to
input int MA1shift = 0; // 1st MA shift
input ENUM_BOOL MA2on = false; // Show second MA
input int MA2period = 50; // 2nd MA period
input ENUM_MA_METHOD_EXT MA2method = _MODE_EMA; // 2nd MA method
input ENUM_APPLIED_PRICE MA2applyTo = PRICE_CLOSE; // 2nd MA apply to
input int MA2shift = 0; // 2nd MA shift
input ENUM_BOOL MA3on = false; // Show third MA
input int MA3period = 20; // 3rd MA period
input ENUM_MA_METHOD_EXT MA3method = _VWAP_TICKVOL; // 3rd MA method
input ENUM_APPLIED_PRICE MA3applyTo = PRICE_CLOSE; // 3rd MA apply to
input int MA3shift = 0; // 3rd MA shift
input ENUM_CHANNEL_TYPE ShowChannel = None; // Show Channel
input string Channel_Settings = "-------------------"; // Channel settings
input int DonchianPeriod = 20; // Donchian Channel period
input ENUM_APPLIED_PRICE BBapplyTo = PRICE_CLOSE; // Bollinger Bands apply to
input int BollingerBandsPeriod = 20; // Bollinger Bands period
input double BollingerBandsDeviations = 2.0; // Bollinger Bands deviations
input int SuperTrendPeriod = 10; // Super Trend period
input double SuperTrendMultiplier=1.7; // Super Trend multiplier
input string Misc_Settings = "-------------------"; // Misc settings
input ENUM_BOOL DisplayAsBarChart = false; // Display as bar chart
input ENUM_BOOL UsedInEA = false; // Indicator used in EA via iCustom()
#else
//
// This block should always be set to the following values
//
double TopBottomPaddingPercentage = 0;
ENUM_PIVOT_POINTS showPivots = ppNone;
ENUM_PIVOT_TYPE pivotPointCalculationType = ppHLC3;
color RColor = clrNONE;
color PColor = clrNONE;
color SColor = clrNONE;
color PDHColor = clrNONE;
color PDLColor = clrNONE;
color PDCColor = clrNONE;
ENUM_BOOL showNextBarLevels = false;
color HighThresholdIndicatorColor = clrNONE;
color LowThresholdIndicatorColor = clrNONE;
ENUM_BOOL showCurrentBarOpenTime = false;
color InfoTextColor = clrNONE;
ENUM_BOOL UseSoundSignalOnNewBar = false;
ENUM_BOOL OnlySignalReversalBars = false;
ENUM_BOOL UseAlertWindow = false;
ENUM_BOOL SendPushNotifications = false;
string SoundFileBull = "";
string SoundFileBear = "";
ENUM_BOOL DisplayAsBarChart = true;
ENUM_BOOL UsedInEA = true; // This should always be set to TRUE for EAs & Indicators
//
//
//
#endif
struct RANGEBAR_SETTINGS
{
int barSizeInTicks;
ENUM_BOOL atrEnabled;
ENUM_TIMEFRAMES atrTimeFrame;
int atrPeriod;
int atrPercentage;
ENUM_BOOL useRealVolume;
ENUM_TICK_PRICE_TYPE plotPrice;
int showNumberOfDays;
ENUM_BOOL resetOpenOnNewTradingDay;
};
class RangeBarSettings
{
protected:
string settingsFileName;
string chartTypeFileName;
RANGEBAR_SETTINGS settings;
CHART_INDICATOR_SETTINGS chartIndicatorSettings;
ALERT_INFO_SETTINGS alertInfoSettings;
public:
RangeBarSettings(void);
~RangeBarSettings(void);
RANGEBAR_SETTINGS GetRangeBarSettings(void);
ALERT_INFO_SETTINGS GetAlertInfoSettings(void);
CHART_INDICATOR_SETTINGS GetChartIndicatorSettings(void);
void Set(void);
void Save(void);
bool Load(void);
void Delete(void);
bool Changed(void);
};
void RangeBarSettings::RangeBarSettings(void)
{
this.settingsFileName = CUSTOM_CHART_NAME+(string)ChartID()+".set";
this.chartTypeFileName = (string)ChartID()+".id";
}
void RangeBarSettings::~RangeBarSettings(void)
{
}
void RangeBarSettings::Save(void)
{
if(IS_TESTING || this.chartIndicatorSettings.UsedInEA)
return;
this.Delete();
//
// Store indicator settings
//
int handle = FileOpen(this.settingsFileName,FILE_SHARE_READ|FILE_WRITE|FILE_BIN);
uint result = 0;
result += FileWriteStruct(handle,this.settings);
result += FileWriteStruct(handle,this.chartIndicatorSettings);
//FileWriteStruct(handle,this.alertInfoSettings);
FileClose(handle);
//
// Store chart type identifier
//
handle = FileOpen(this.chartTypeFileName,FILE_SHARE_READ|FILE_WRITE|FILE_ANSI);
FileWriteString(handle,CUSTOM_CHART_NAME);
FileClose(handle);
}
void RangeBarSettings::Delete(void)
{
if(IS_TESTING || this.chartIndicatorSettings.UsedInEA)
return;
if(FileIsExist(this.settingsFileName))
FileDelete(this.settingsFileName);
}
bool RangeBarSettings::Load(void)
{
#ifdef SHOW_INDICATOR_INPUTS
Set();
return true;
#else
if(!FileIsExist(this.settingsFileName))
return false;
int handle = FileOpen(this.settingsFileName,FILE_SHARE_READ|FILE_BIN);
if(handle == INVALID_HANDLE)
return false;
if(FileReadStruct(handle,this.settings) <= 0)
{
Print("Failed loading settings(1)!");
FileClose(handle);
return false;
}
if(FileReadStruct(handle,this.chartIndicatorSettings) <= 0)
{
Print("Failed loading settings(2)!");
FileClose(handle);
return false;
}
/*
if(FileReadStruct(handle,this.alertInfoSettings) <= 0)
{
Print("Failed loading settings(3)!");
FileClose(handle);
return false;
}
*/
FileClose(handle);
return true;
#endif
}
ALERT_INFO_SETTINGS RangeBarSettings::GetAlertInfoSettings(void)
{
return this.alertInfoSettings;
}
CHART_INDICATOR_SETTINGS RangeBarSettings::GetChartIndicatorSettings(void)
{
return this.chartIndicatorSettings;
}
RANGEBAR_SETTINGS RangeBarSettings::GetRangeBarSettings(void)
{
return this.settings;
}
void RangeBarSettings::Set(void)
{
#ifdef SHOW_INDICATOR_INPUTS
settings.barSizeInTicks = barSizeInTicks;
settings.atrEnabled = atrEnabled;
settings.atrTimeFrame = atrTimeFrame;
settings.atrPeriod = atrPeriod;
settings.atrPercentage = atrPercentage;
settings.useRealVolume = useRealVolume;
settings.plotPrice = plotPrice;
settings.showNumberOfDays = showNumberOfDays;
settings.resetOpenOnNewTradingDay = resetOpenOnNewTradingDay;
//
//
//
chartIndicatorSettings.MA1on = MA1on;
chartIndicatorSettings.MA1period = MA1period;
chartIndicatorSettings.MA1method = MA1method;
chartIndicatorSettings.MA1applyTo = MA1applyTo;
chartIndicatorSettings.MA1shift = MA1shift;
chartIndicatorSettings.MA2on = MA2on;
chartIndicatorSettings.MA2period = MA2period;
chartIndicatorSettings.MA2method = MA2method;
chartIndicatorSettings.MA2applyTo = MA2applyTo;
chartIndicatorSettings.MA2shift = MA2shift;
/*
chartIndicatorSettings.ShowVWAP = ShowVWAP;
chartIndicatorSettings.VWAP_Period = VWAP_Period;
chartIndicatorSettings.VWAPapplyTo = VWAPapplyTo;
chartIndicatorSettings.VWAPvolume = VWAPvolume;
*/
chartIndicatorSettings.MA3on = MA3on;
chartIndicatorSettings.MA3period = MA3period;
chartIndicatorSettings.MA3method = MA3method;
chartIndicatorSettings.MA3applyTo = MA3applyTo;
chartIndicatorSettings.MA3shift = MA3shift;
chartIndicatorSettings.ShowChannel = ShowChannel;
chartIndicatorSettings.DonchianPeriod = DonchianPeriod;
chartIndicatorSettings.BBapplyTo = BBapplyTo;
chartIndicatorSettings.BollingerBandsPeriod = BollingerBandsPeriod;
chartIndicatorSettings.BollingerBandsDeviations = BollingerBandsDeviations;
chartIndicatorSettings.SuperTrendPeriod = SuperTrendPeriod;
chartIndicatorSettings.SuperTrendMultiplier = SuperTrendMultiplier;
chartIndicatorSettings.UsedInEA = UsedInEA;
//
//
//
alertInfoSettings.TopBottomPaddingPercentage = TopBottomPaddingPercentage;
alertInfoSettings.showPiovots = showPivots;
alertInfoSettings.pivotPointCalculationType = pivotPointCalculationType;
alertInfoSettings.Rcolor = RColor;
alertInfoSettings.Pcolor = PColor;
alertInfoSettings.Scolor = SColor;
alertInfoSettings.PDHColor = PDHColor;
alertInfoSettings.PDLColor = PDLColor;
alertInfoSettings.PDCColor = PDCColor;
alertInfoSettings.showNextBarLevels = showNextBarLevels;
alertInfoSettings.HighThresholdIndicatorColor = HighThresholdIndicatorColor;
alertInfoSettings.LowThresholdIndicatorColor = LowThresholdIndicatorColor;
alertInfoSettings.showCurrentBarOpenTime = showCurrentBarOpenTime;
alertInfoSettings.InfoTextColor = InfoTextColor;
alertInfoSettings.UseSoundSignalOnNewBar = UseSoundSignalOnNewBar;
alertInfoSettings.OnlySignalReversalBars = OnlySignalReversalBars;
alertInfoSettings.UseAlertWindow = UseAlertWindow;
alertInfoSettings.SendPushNotifications = SendPushNotifications;
alertInfoSettings.SoundFileBull = SoundFileBull;
alertInfoSettings.SoundFileBear = SoundFileBear;
alertInfoSettings.DisplayAsBarChart = DisplayAsBarChart;
#endif
}
bool RangeBarSettings::Changed(void)
{
if(MQLInfoInteger((int)MQL5_TESTING))
return false;
static datetime prevFileTime = 0;
if(!FileIsExist(this.settingsFileName))
return false;
int handle = FileOpen(this.settingsFileName,FILE_SHARE_READ|FILE_BIN);
datetime currFileTime = (datetime)FileGetInteger(handle,FILE_CREATE_DATE);
FileClose(handle);
if(prevFileTime != currFileTime)
{
prevFileTime = currFileTime;
return true;
}
return false;
}
+265 -119
View File
@@ -1,89 +1,120 @@
//+------------------------------------------------------------------+
//| RangeBars.mqh ver:2.03.0 |
//| Copyright 2017, AZ-iNVEST |
//| http://www.az-invest.eu |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, AZ-iNVEST"
#property copyright "Copyright 2018-2020, Level Up Software"
#property link "http://www.az-invest.eu"
#define RANGEBAR_INDICATOR_NAME "Market\\Range Bars Charting"
//#define RANGEBAR_INDICATOR_NAME "RangeBars\\RangeBarsOverlay203"
#ifdef DEVELOPER_VERSION
#define RANGEBAR_INDICATOR_NAME "RangeBars\\RangeBarsOverlay300"
#else
#ifdef RANGEBAR_LICENSE
#ifdef MQL5_MARKET_VERSION
#define RANGEBAR_INDICATOR_NAME "Market\\Range Bars Charting"
#else
#define RANGEBAR_INDICATOR_NAME "RangeBars"
#endif
#else
#define RANGEBAR_INDICATOR_NAME "Market\\Range Bars Charting"
#endif
#endif
#define RANGEBAR_OPEN 00
#define RANGEBAR_HIGH 01
#define RANGEBAR_LOW 02
#define RANGEBAR_CLOSE 03
#define RANGEBAR_BAR_COLOR 04
#define RANGEBAR_MA1 05
#define RANGEBAR_MA2 06
#define RANGEBAR_MA3 07
#define RANGEBAR_CHANNEL_HIGH 08
#define RANGEBAR_CHANNEL_MID 09
#define RANGEBAR_CHANNEL_LOW 10
#define RANGEBAR_BAR_OPEN_TIME 11
#define RANGEBAR_TICK_VOLUME 12
#define RANGEBAR_REAL_VOLUME 13
#define RANGEBAR_BUY_VOLUME 14
#define RANGEBAR_SELL_VOLUME 15
#define RANGEBAR_BUYSELL_VOLUME 16
#define RANGEBAR_SESSION_RECT_H 05
#define RANGEBAR_SESSION_RECT_L 06
#define RANGEBAR_MA1 07
#define RANGEBAR_MA2 08
#define RANGEBAR_MA3 09
#define RANGEBAR_MA4 10
#define RANGEBAR_CHANNEL_HIGH 11
#define RANGEBAR_CHANNEL_MID 12
#define RANGEBAR_CHANNEL_LOW 13
#define RANGEBAR_BAR_OPEN_TIME 14
#define RANGEBAR_TICK_VOLUME 15
#define RANGEBAR_REAL_VOLUME 16
#define RANGEBAR_BUY_VOLUME 17
#define RANGEBAR_SELL_VOLUME 18
#define RANGEBAR_BUYSELL_VOLUME 19
#define RANGEBAR_RUNTIME_ID 20
#include <AZ-INVEST/SDK/RangeBarSettings.mqh>
#include <az-invest/sdk/RangeBarCustomChartSettings.mqh>
class RangeBars
{
private:
RangeBarSettings * rangeBarSettings;
CRangeBarCustomChartSettigns * rangeBarSettings;
//
// Median renko indicator handle
//
int rangeBarsHandle;
int rangeBarsHandle; // range bar indicator handle
string rangeBarsSymbol;
bool usedByIndicatorOnRangeBarChart;
datetime prevBarTime;
public:
RangeBars();
RangeBars(bool isUsedByIndicatorOnRangeBarChart);
RangeBars(string symbol);
~RangeBars(void);
int Init();
void Deinit();
bool Reload();
void ReleaseHandle();
int GetHandle(void) { return rangeBarsHandle; };
double GetRuntimeId();
bool IsNewBar();
bool GetMqlRates(MqlRates &ratesInfoArray[], int start, int count);
bool GetBuySellVolumeBreakdown(double &buy[], double &sell[], double &buySell[], int start, int count);
bool GetMA(int MaBufferId, double &MA[], int start, int count);
bool GetChannel(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count);
// The following 6 functions are deprecated, please use GetMA & GetChannelData functions instead
bool GetMA1(double &MA[], int start, int count);
bool GetMA2(double &MA[], int start, int count);
bool GetMA3(double &MA[], int start, int count);
bool GetDonchian(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count);
bool GetBollingerBands(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count);
bool GetSuperTrend(double &SuperTrendHighArray[], double &SuperTrendArray[], double &SuperTrendLowArray[], int start, int count);
bool IsNewBar();
//
private:
bool GetChannel(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count);
int GetIndicatorHandle(void);
bool GetChannelData(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count);
};
RangeBars::RangeBars(void)
{
#define CONSTRUCTOR1
rangeBarSettings = new RangeBarSettings();
rangeBarSettings = new CRangeBarCustomChartSettigns();
rangeBarsHandle = INVALID_HANDLE;
rangeBarsSymbol = _Symbol;
usedByIndicatorOnRangeBarChart = false;
prevBarTime = 0;
}
RangeBars::RangeBars(bool isUsedByIndicatorOnRangeBarChart)
{
rangeBarSettings = new CRangeBarCustomChartSettigns();
rangeBarsHandle = INVALID_HANDLE;
rangeBarsSymbol = _Symbol;
usedByIndicatorOnRangeBarChart = isUsedByIndicatorOnRangeBarChart;
prevBarTime = 0;
}
RangeBars::RangeBars(string symbol)
{
#define CONSTRUCTOR2
rangeBarSettings = new RangeBarSettings();
rangeBarSettings = new CRangeBarCustomChartSettigns();
rangeBarsHandle = INVALID_HANDLE;
rangeBarsSymbol = symbol;
usedByIndicatorOnRangeBarChart = false;
prevBarTime = 0;
}
RangeBars::~RangeBars(void)
@@ -92,6 +123,14 @@ RangeBars::~RangeBars(void)
delete rangeBarSettings;
}
void RangeBars::ReleaseHandle()
{
if(rangeBarsHandle != INVALID_HANDLE)
{
IndicatorRelease(rangeBarsHandle);
}
}
//
// Function for initializing the median renko indicator handle
//
@@ -100,6 +139,18 @@ int RangeBars::Init()
{
if(!MQLInfoInteger((int)MQL5_TESTING))
{
if(usedByIndicatorOnRangeBarChart)
{
//
// Indicator on RangeBar chart uses the values of the RangeBar chart for calculations
//
IndicatorRelease(rangeBarsHandle);
rangeBarsHandle = GetIndicatorHandle();
return rangeBarsHandle;
}
if(!rangeBarSettings.Load())
{
if(rangeBarsHandle != INVALID_HANDLE)
@@ -121,87 +172,94 @@ int RangeBars::Init()
}
else
{
#ifdef SHOW_INDICATOR_INPUTS
if(usedByIndicatorOnRangeBarChart)
{
//
// Load settings from EA inputs
//
rangeBarSettings.Load();
#else
//
// Save indicator inputs for use by EA attached to same chart.
//
rangeBarSettings.Save();
#endif
// Indicator on RangeBar chart uses the values of the RangeBar chart for calculations
//
rangeBarsHandle = GetIndicatorHandle();
return rangeBarsHandle;
}
else
{
#ifdef SHOW_INDICATOR_INPUTS
//
// Load settings from EA inputs
//
rangeBarSettings.Load();
#endif
}
}
RANGEBAR_SETTINGS s = rangeBarSettings.GetRangeBarSettings();
RANGEBAR_SETTINGS s = rangeBarSettings.GetCustomChartSettings();
CHART_INDICATOR_SETTINGS cis = rangeBarSettings.GetChartIndicatorSettings();
//RangeBarSettings.Debug();
rangeBarsHandle = iCustom(this.rangeBarsSymbol,_Period,RANGEBAR_INDICATOR_NAME,
rangeBarsHandle = iCustom(this.rangeBarsSymbol, _Period, RANGEBAR_INDICATOR_NAME,
s.barSizeInTicks,
s.showNumberOfDays,
"=",
s.atrEnabled,
//s.atrTimeFrame,
s.atrTimeFrame,
s.atrPeriod,
s.atrPercentage,
s.showNumberOfDays,
"=",
s.resetOpenOnNewTradingDay,
TopBottomPaddingPercentage,
"=",
showPivots,
pivotPointCalculationType,
RColor,
PColor,
SColor,
PDHColor,
PDLColor,
PDCColor,
showNextBarLevels,
HighThresholdIndicatorColor,
LowThresholdIndicatorColor,
showCurrentBarOpenTime,
InfoTextColor,
UseSoundSignalOnNewBar,
OnlySignalReversalBars,
UseAlertWindow,
SendPushNotifications,
SoundFileBull,
SoundFileBear,
cis.MA1on,
"=",
AlertMeWhen,
AlertNotificationType,
"=",
cis.MA1lineType,
cis.MA1period,
cis.MA1method,
cis.MA1applyTo,
cis.MA1shift,
cis.MA2on,
cis.MA1priceLabel,
cis.MA2lineType,
cis.MA2period,
cis.MA2method,
cis.MA2applyTo,
cis.MA2shift,
cis.MA3on,
cis.MA2priceLabel,
cis.MA3lineType,
cis.MA3period,
cis.MA3method,
cis.MA3applyTo,
cis.MA3shift,
cis.MA3priceLabel,
cis.MA4lineType,
cis.MA4period,
cis.MA4method,
cis.MA4applyTo,
cis.MA4shift,
cis.MA4priceLabel,
"=",
cis.ShowChannel,
"",
cis.DonchianPeriod,
cis.BBapplyTo,
cis.BollingerBandsPeriod,
cis.BollingerBandsDeviations,
cis.SuperTrendPeriod,
cis.SuperTrendMultiplier,
"",
DisplayAsBarChart,
UsedInEA);
cis.ChannelPeriod,
cis.ChannelAtrPeriod,
cis.ChannelAppliedPrice,
cis.ChannelMultiplier,
cis.ChannelBandsDeviations,
cis.ChannelPriceLabel,
cis.ChannelMidPriceLabel,
"=",
true); // used in EA
// TopBottomPaddingPercentage,
// showCurrentBarOpenTime,
// SoundFileBull,
// SoundFileBear,
// DisplayAsBarChart
// ShiftObj; all letft at defaults
if(rangeBarsHandle == INVALID_HANDLE)
{
Print("RangeBar indicator init failed on error ",GetLastError());
Print(RANGEBAR_INDICATOR_NAME+" indicator init failed on error ",GetLastError());
}
else
{
Print("RangeBar indicator init OK");
Print(RANGEBAR_INDICATOR_NAME+" indicator init OK");
}
return rangeBarsHandle;
@@ -213,14 +271,36 @@ int RangeBars::Init()
bool RangeBars::Reload()
{
if(rangeBarSettings.Changed())
bool actionNeeded = false;
int temp = GetIndicatorHandle();
if(temp != rangeBarsHandle)
{
if(Init() == INVALID_HANDLE)
return false;
return true;
IndicatorRelease(rangeBarsHandle);
rangeBarsHandle = INVALID_HANDLE;
actionNeeded = true;
}
if(rangeBarSettings.Changed(GetRuntimeId()))
{
actionNeeded = true;
}
if(actionNeeded)
{
if(rangeBarsHandle != INVALID_HANDLE)
{
IndicatorRelease(rangeBarsHandle);
rangeBarsHandle = INVALID_HANDLE;
}
if(Init() == INVALID_HANDLE)
return false;
return true;
}
return false;
}
@@ -233,10 +313,13 @@ void RangeBars::Deinit()
if(rangeBarsHandle == INVALID_HANDLE)
return;
if(IndicatorRelease(rangeBarsHandle))
Print("RangeBar indicator handle released");
else
Print("Failed to release RangeBar indicator handle");
if(!usedByIndicatorOnRangeBarChart)
{
if(IndicatorRelease(rangeBarsHandle))
Print(RANGEBAR_INDICATOR_NAME+" indicator handle released");
else
Print("Failed to release "+RANGEBAR_INDICATOR_NAME+" indicator handle");
}
}
//
@@ -245,13 +328,13 @@ void RangeBars::Deinit()
bool RangeBars::IsNewBar()
{
MqlRates currentBar[1];
static datetime prevBarTime;
MqlRates currentBar[1];
GetMqlRates(currentBar,0,1);
if(currentBar[0].time == 0)
{
return false;
}
if(prevBarTime < currentBar[0].time)
{
@@ -259,7 +342,8 @@ bool RangeBars::IsNewBar()
return true;
}
return false;}
return false;
}
//
// Get "count" Renko MqlRates into "ratesInfoArray[]" array starting from "start" bar
@@ -342,23 +426,12 @@ bool RangeBars::GetBuySellVolumeBreakdown(double &buy[], double &sell[], double
if(ArrayResize(bs,count) == -1)
return false;
#ifdef P_RANGEBAR_BR
#ifdef P_RANGEBAR_BR_PRO
if(CopyBuffer(rangeBarsHandle,RANGEBAR_BUY_VOLUME,start,count,b) == -1)
return false;
if(CopyBuffer(rangeBarsHandle,RANGEBAR_SELL_VOLUME,start,count,s) == -1)
return false;
if(CopyBuffer(rangeBarsHandle,RANGEBAR_BUYSELL_VOLUME,start,count,bs) == -1)
return false;
#endif
#else
if(CopyBuffer(rangeBarsHandle,RANGEBAR_BUY_VOLUME,start,count,b) == -1)
return false;
if(CopyBuffer(rangeBarsHandle,RANGEBAR_SELL_VOLUME,start,count,s) == -1)
return false;
if(CopyBuffer(rangeBarsHandle,RANGEBAR_BUYSELL_VOLUME,start,count,bs) == -1)
return false;
#endif
if(ArrayResize(buy,count) == -1)
return false;
@@ -380,16 +453,48 @@ bool RangeBars::GetBuySellVolumeBreakdown(double &buy[], double &sell[], double
ArrayFree(bs);
return true;
}
//
// Get "count" values for MaBufferId buffer into "MA[]" array starting from "start" bar
//
bool RangeBars::GetMA(int MaBufferId, double &MA[], int start, int count)
{
double tempMA[];
if(ArrayResize(tempMA, count) == -1)
return false;
if(ArrayResize(MA, count) == -1)
return false;
if(MaBufferId != RANGEBAR_MA1 && MaBufferId != RANGEBAR_MA2 && MaBufferId != RANGEBAR_MA3 && MaBufferId != RANGEBAR_MA4)
{
Print("Incorrect MA buffer id specified in "+__FUNCTION__);
return false;
}
if(CopyBuffer(rangeBarsHandle, MaBufferId,start,count,tempMA) == -1)
{
return false;
}
for(int i=0; i<count; i++)
{
MA[count-1-i] = tempMA[i];
}
ArrayFree(tempMA);
return true;
}
//
// Get "count" MovingAverage1 values into "MA[]" array starting from "start" bar
//
bool RangeBars::GetMA1(double &MA[], int start, int count)
{
Print(__FUNCTION__+" is deprecated, please use GetMA instead");
double tempMA[];
if(ArrayResize(tempMA,count) == -1)
return false;
@@ -415,6 +520,8 @@ bool RangeBars::GetMA1(double &MA[], int start, int count)
bool RangeBars::GetMA2(double &MA[], int start, int count)
{
Print(__FUNCTION__+" is deprecated, please use GetMA instead");
double tempMA[];
if(ArrayResize(tempMA,count) == -1)
return false;
@@ -440,6 +547,8 @@ bool RangeBars::GetMA2(double &MA[], int start, int count)
bool RangeBars::GetMA3(double &MA[], int start, int count)
{
Print(__FUNCTION__+" is deprecated, please use GetMA instead");
double tempMA[];
if(ArrayResize(tempMA,count) == -1)
return false;
@@ -460,12 +569,13 @@ bool RangeBars::GetMA3(double &MA[], int start, int count)
}
//
// Get "count" Renko Donchian channel values into "HighArray[]", "MidArray[]", and "LowArray[]" arrays starting from "start" bar
// Get "count" Donchian channel values into "HighArray[]", "MidArray[]", and "LowArray[]" arrays starting from "start" bar
//
bool RangeBars::GetDonchian(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count)
{
return GetChannel(HighArray,MidArray,LowArray,start,count);
Print(__FUNCTION__+" is deprecated, please use GetChannelData instead");
return GetChannelData(HighArray,MidArray,LowArray,start,count);
}
//
@@ -474,7 +584,8 @@ bool RangeBars::GetDonchian(double &HighArray[], double &MidArray[], double &Low
bool RangeBars::GetBollingerBands(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count)
{
return GetChannel(HighArray,MidArray,LowArray,start,count);
Print(__FUNCTION__+" is deprecated, please use GetChannelData instead");
return GetChannelData(HighArray,MidArray,LowArray,start,count);
}
//
@@ -483,21 +594,27 @@ bool RangeBars::GetBollingerBands(double &HighArray[], double &MidArray[], doubl
bool RangeBars::GetSuperTrend(double &SuperTrendHighArray[], double &SuperTrendArray[], double &SuperTrendLowArray[], int start, int count)
{
return GetChannel(SuperTrendHighArray,SuperTrendArray,SuperTrendLowArray,start,count);
Print(__FUNCTION__+" is deprecated, please use GetChannel function instead");
return GetChannelData(SuperTrendHighArray,SuperTrendArray,SuperTrendLowArray,start,count);
}
//
// Get Channel values into "HighArray[]", "MidArray[]", and "LowArray[]" arrays starting from "start" bar
//
bool RangeBars::GetChannel(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count)
{
return GetChannelData(HighArray,MidArray,LowArray,start,count);
}
//
// Private function used by GetRenkoDonchian and GetRenkoBollingerBands functions to get data
//
bool RangeBars::GetChannel(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count)
bool RangeBars::GetChannelData(double &HighArray[], double &MidArray[], double &LowArray[], int start, int count)
{
double tempH[], tempM[], tempL[];
#ifdef P_RANGEBAR_BR
return false;
#else
if(ArrayResize(tempH,count) == -1)
return false;
if(ArrayResize(tempM,count) == -1)
@@ -532,6 +649,35 @@ bool RangeBars::GetChannel(double &HighArray[], double &MidArray[], double &LowA
ArrayFree(tempL);
return true;
#endif
}
int RangeBars::GetIndicatorHandle(void)
{
int i = ChartIndicatorsTotal(0,0);
int j=0;
string iName;
while(j < i)
{
iName = ChartIndicatorName(0,0,j);
if(StringFind(iName,CUSTOM_CHART_NAME) != -1)
{
return ChartIndicatorGet(0,0,iName);
}
j++;
}
Print("Failed getting handle of "+CUSTOM_CHART_NAME);
return INVALID_HANDLE;
}
double RangeBars::GetRuntimeId()
{
double runtimeId[1];
if(CopyBuffer(rangeBarsHandle, RANGEBAR_RUNTIME_ID, 0, 1, runtimeId) == -1)
return -1;
return runtimeId[0];
}
+76
View File
@@ -0,0 +1,76 @@
//
// Copyright 2018-19, Artur Zas
// https://www.az-invest.eu
// https://www.mql5.com/en/users/arturz
//
class CTimeControl
{
private:
int startHH;
int startMM;
string start;
int endHH;
int endMM;
string end;
bool scheduleEnabled;
public:
void SetValidTraingHours(string _from = "0:00", string _to = "0:00");
bool IsTradingTimeValid();
bool IsScheduleEnabled() { return scheduleEnabled; };
void StringToHHMM(string value, int &HH, int &MM);
};
void CTimeControl::SetValidTraingHours(string _from,string _to)
{
this.start = _from;
this.end = _to;
StringToHHMM(this.start, this.startHH, this.startMM);
StringToHHMM(this.end, this.endHH, this.endMM);
if(this.startHH == 0 && this.startMM == 0 && this.endHH == 0 && this.endMM == 0)
{
scheduleEnabled = false;
}
else
{
scheduleEnabled = true;
}
}
bool CTimeControl::IsTradingTimeValid()
{
if(scheduleEnabled == false)
return true;
datetime now = TimeCurrent();
MqlDateTime temp;
TimeToStruct(now,temp);
datetime _start = StringToTime((string)temp.year+"."+(string)temp.mon+"."+(string)temp.day+" "+this.start);
datetime _end = StringToTime((string)temp.year+"."+(string)temp.mon+"."+(string)temp.day+" "+this.end);
if((now >= _start) && (now <= _end))
return true;
else
return false;
}
void CTimeControl::StringToHHMM(string value, int &HH, int &MM)
{
MqlDateTime temp;
TimeToStruct(TimeCurrent(),temp);
datetime fullDateTime = StringToTime((string)temp.year+"."+(string)temp.mon+"."+(string)temp.day+" "+value);
TimeToStruct(fullDateTime,temp);
HH = temp.hour;
MM = temp.min;
}
+545 -80
View File
@@ -1,11 +1,13 @@
//+------------------------------------------------------------------+
//| TradeFunctions.mqh |
//| Copyright 2017, AZ-iNVEST |
//| http://www.az-invest.eu |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, AZ-iNVEST"
#property link "http://www.az-invest.eu"
//
// Copyright 2017-2018, Artur Zas
// https://www.az-invest.eu
// https://www.mql5.com/en/users/arturz
//
#include <Trade\Trade.mqh>
#include <AZ-INVEST/SDK/Normailze.mqh>
#include <AZ-INVEST/SDK/TradingChecks.mqh>
CTradingChecks tradingChecks;
#define POSITION_TYPE_NONE -1
@@ -15,40 +17,58 @@
struct CMarketOrderParameters
{
bool m_async_mode; // trade mode
ulong m_magic; // expert magic number
ulong m_deviation; // deviation default
bool m_async_mode; // trade mode
ulong m_magic; // expert magic number
ulong m_deviation; // deviation default
ENUM_ORDER_TYPE_FILLING m_type_filling;
int numberOfRetries;
int busyTimeout_ms;
int requoteTimeout_ms;
int numberOfRetries;
int busyTimeout_ms;
int requoteTimeout_ms;
};
class CMarketOrder
{
protected:
CTrade * ctrade;
CTrade *ctrade;
int numberOfRetries;
int busyTimeout_ms;
int requoteTimeout_ms;
bool initialized;
int numberOfRetries;
int busyTimeout_ms;
int requoteTimeout_ms;
public:
CMarketOrder(void);
CMarketOrder(CMarketOrderParameters &params);
~CMarketOrder(void);
bool Long(string symbol, double lots, uint stoploss = 0, uint takeprofit = 0);
bool Long(string symbol,double lots, double priceSL=0,double priceTP=0);
bool Short(string symbol,double lots, uint stoploss = 0, uint takeprofit = 0);
bool Short(string symbol,double lots, double priceSL=0,double priceTP=0);
bool Modify(ulong ticket, uint stoploss = 0, uint takeprofit = 0);
bool Initialize(CMarketOrderParameters &params);
bool IsInitialized() {return initialized;};
bool Long(string symbol, double lots, uint stoploss = 0, uint takeprofit = 0,bool stopsInPips = true, string comment = "");
bool Long(string symbol,double lots, double priceSL=0,double priceTP=0, string comment = "");
bool Short(string symbol,double lots, uint stoploss = 0, uint takeprofit = 0,bool stopsInPips = true, string comment = "");
bool Short(string symbol,double lots, double priceSL=0,double priceTP=0, string comment = "");
bool PendingLong(ENUM_ORDER_TYPE orderType, string symbol, double lots, double price, uint stoploss=0,uint takeprofit=0,bool stopsInPips = true, string comment = "");
bool PendingLong(ENUM_ORDER_TYPE orderType, string symbol, double lots, double price, double priceSL=0, double priceTP=0, string comment = "");
bool PendingShort(ENUM_ORDER_TYPE orderType, string symbol, double lots, double price, uint stoploss=0,uint takeprofit=0,bool stopsInPips = true, string comment = "");
bool PendingShort(ENUM_ORDER_TYPE orderType, string symbol, double lots, double price, double priceSL=0, double priceTP=0, string comment = "");
bool Modify(ulong ticket, bool stopsInPips = true, int stoploss = -1, int takeprofit = -1);
bool Modify(ulong ticket, double priceSL=0,double priceTP=0);
bool ModifyPending(ulong ticket, double entry, bool stopsInPips = true, int stoploss = -1, int takeprofit = -1, ENUM_ORDER_TYPE_TIME orderTypeTime = ORDER_TIME_GTC, datetime expires = 0);
bool ModifyPending(ulong ticket, double entry, double priceSL=0, double priceTP=0, ENUM_ORDER_TYPE_TIME orderTypeTime = ORDER_TIME_GTC, datetime expires = 0);
bool Close(ulong ticket);
bool ClosePartial(ulong ticket, double lots);
bool CloseAll(string symbol = "");
bool Delete(ulong ticket);
bool Reverse(ulong ticket,double lots = 0, uint stoploss=0, uint takeprofit=0);
bool Reverse(ulong ticket,double lots = 0, double priceSL=0,double priceTP=0);
bool IsOpen(string symbol, ENUM_POSITION_TYPE type, long magicNumber = 0);
@@ -57,8 +77,13 @@ class CMarketOrder
bool IsOpen(ulong &ticket, string symbol, long magicNumber = 0);
bool IsOpen(ulong &ticket, ENUM_POSITION_TYPE &type, string symbol, long magicNumber = 0);
bool GetPositionType(ulong ticket, ENUM_POSITION_TYPE &_pType);
string PositionTypeToString(ENUM_POSITION_TYPE t);
string OrderTypeToString(ENUM_ORDER_TYPE t);
ENUM_ORDER_TYPE TradeBias(ENUM_ORDER_TYPE t);
bool RetryOrderRequest(int retryNumber);
void SetTradeId(ulong tradeId);
private:
@@ -68,19 +93,31 @@ class CMarketOrder
};
CMarketOrder::CMarketOrder(void)
{
ctrade = new CTrade();
this.initialized = false;
}
CMarketOrder::CMarketOrder(CMarketOrderParameters &params)
{
ctrade = new CTrade();
Initialize(params);
}
bool CMarketOrder::Initialize(CMarketOrderParameters &params)
{
ctrade.SetExpertMagicNumber(params.m_magic);
ctrade.SetDeviationInPoints(params.m_deviation);
ctrade.SetTypeFilling(params.m_type_filling);
ctrade.SetAsyncMode(params.m_async_mode);
this.numberOfRetries = (params.numberOfRetries == 0) ? 25 : params.numberOfRetries;
this.busyTimeout_ms = (params.busyTimeout_ms == 0) ? 1000 : params.busyTimeout_ms;
this.requoteTimeout_ms = (params.requoteTimeout_ms == 0) ? 250 : params.requoteTimeout_ms;
this.numberOfRetries = (params.numberOfRetries == 0) ? 25 : params.numberOfRetries;
this.busyTimeout_ms = (params.busyTimeout_ms == 0) ? 1000 : params.busyTimeout_ms;
this.requoteTimeout_ms = (params.requoteTimeout_ms == 0) ? 250 : params.requoteTimeout_ms;
this.initialized = true;
return this.initialized;
}
CMarketOrder::~CMarketOrder(void)
@@ -89,7 +126,7 @@ CMarketOrder::~CMarketOrder(void)
delete ctrade;
}
bool CMarketOrder::Long(string symbol, double lots,uint stoploss=0,uint takeprofit=0)
bool CMarketOrder::Long(string symbol, double lots,uint stoploss=0,uint takeprofit=0,bool stopsInPips = true, string comment = "")
{
bool result = false;
int counter = 0;
@@ -97,14 +134,21 @@ bool CMarketOrder::Long(string symbol, double lots,uint stoploss=0,uint takeprof
while(!IsStopped() && !result)
{
double price = SymbolInfoDouble(symbol,SYMBOL_ASK);
double _point = SymbolInfoDouble(symbol,SYMBOL_POINT);
double point = SymbolInfoDouble(symbol,SYMBOL_POINT);
//calc SL + TP
double priceSL = (stoploss ? NormalizePrice(symbol,price - stoploss*_point) : 0.0);
double priceTP = (takeprofit ? NormalizePrice(symbol,price + takeprofit*_point) : 0.0);
double priceSL = (stoploss ? NormalizePrice(symbol,price - stoploss*point) : 0.0);
double priceTP = (takeprofit ? NormalizePrice(symbol,price + takeprofit*point) : 0.0);
//do checks
if(!tradingChecks.OkToOpenPosition(symbol,ORDER_TYPE_BUY,lots,price,priceSL,priceTP))
{
Alert("Unable to place trade: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to buy
result = ctrade.Buy(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP);
result = ctrade.Buy(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP, comment);
if(result)
{
@@ -121,7 +165,7 @@ bool CMarketOrder::Long(string symbol, double lots,uint stoploss=0,uint takeprof
return false;
}
bool CMarketOrder::Long(string symbol, double lots,double priceSL=0,double priceTP=0)
bool CMarketOrder::Long(string symbol, double lots,double priceSL=0,double priceTP=0, string comment = "")
{
bool result = false;
int counter = 0;
@@ -130,8 +174,15 @@ bool CMarketOrder::Long(string symbol, double lots,double priceSL=0,double price
{
double price = SymbolInfoDouble(symbol,SYMBOL_ASK);
//do checks
if(!tradingChecks.OkToOpenPosition(symbol,ORDER_TYPE_BUY,lots,price,priceSL,priceTP))
{
Alert("Unable to place trade: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to buy
result = ctrade.Buy(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP);
result = ctrade.Buy(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP, comment);
if(result)
{
@@ -148,7 +199,7 @@ bool CMarketOrder::Long(string symbol, double lots,double priceSL=0,double price
return false;
}
bool CMarketOrder::Short(string symbol, double lots,uint stoploss=0,uint takeprofit=0)
bool CMarketOrder::Short(string symbol, double lots,uint stoploss=0,uint takeprofit=0,bool stopsInPips = true, string comment = "")
{
bool result = false;
int counter = 0;
@@ -156,14 +207,21 @@ bool CMarketOrder::Short(string symbol, double lots,uint stoploss=0,uint takepro
while(!IsStopped() && !result)
{
double price = SymbolInfoDouble(symbol,SYMBOL_BID);
double _point = SymbolInfoDouble(symbol,SYMBOL_POINT);
double point = SymbolInfoDouble(symbol,SYMBOL_POINT);
//calc SL + TP
double priceSL = (stoploss ? NormalizePrice(symbol,price + stoploss*_point) : 0.0);
double priceTP = (takeprofit ? NormalizePrice(symbol,price - takeprofit*_point) : 0.0);
double priceSL = (stoploss ? NormalizePrice(symbol,price + stoploss*point) : 0.0);
double priceTP = (takeprofit ? NormalizePrice(symbol,price - takeprofit*point) : 0.0);
//do checks
if(!tradingChecks.OkToOpenPosition(symbol,ORDER_TYPE_SELL,lots,price,priceSL,priceTP))
{
Alert("Unable to place trade: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to sell
result = ctrade.Sell(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP);
result = ctrade.Sell(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP, comment);
if(result)
{
@@ -180,7 +238,7 @@ bool CMarketOrder::Short(string symbol, double lots,uint stoploss=0,uint takepro
return false;
}
bool CMarketOrder::Short(string symbol, double lots,double priceSL=0,double priceTP=0)
bool CMarketOrder::Short(string symbol, double lots,double priceSL=0,double priceTP=0, string comment = "")
{
bool result = false;
int counter = 0;
@@ -189,8 +247,15 @@ bool CMarketOrder::Short(string symbol, double lots,double priceSL=0,double pric
{
double price = SymbolInfoDouble(symbol,SYMBOL_BID);
//do checks
if(!tradingChecks.OkToOpenPosition(symbol,ORDER_TYPE_SELL,lots,price,priceSL,priceTP))
{
Alert("Unable to place trade: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to sell
result = ctrade.Sell(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP);
result = ctrade.Sell(NormalizeLots(symbol,lots), symbol, price, priceSL, priceTP, comment);
if(result)
{
@@ -207,24 +272,202 @@ bool CMarketOrder::Short(string symbol, double lots,double priceSL=0,double pric
return false;
}
bool CMarketOrder::Modify(ulong ticket, uint stoploss = 0, uint takeprofit = 0)
bool CMarketOrder::PendingLong(ENUM_ORDER_TYPE orderType, string symbol, double lots, double price, uint stoploss=0,uint takeprofit=0,bool stopsInPips = true, string comment = "")
{
bool result = false;
while(!IsStopped() && !result)
{
double point = SymbolInfoDouble(symbol,SYMBOL_POINT);
//calc SL + TP
double priceSL = (stoploss ? NormalizePrice(symbol,price - stoploss*point) : 0.0);
double priceTP = (takeprofit ? NormalizePrice(symbol,price + takeprofit*point) : 0.0);
//do checks
if(!tradingChecks.OkToOpenPosition(symbol,orderType,lots,price,priceSL,priceTP))
{
Alert("Unable to place trade: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to place buy
if(orderType == ORDER_TYPE_BUY_LIMIT)
result = ctrade.BuyLimit(NormalizeLots(symbol,lots),price,symbol,priceSL,priceTP,ORDER_TIME_GTC,0,comment);
else if(orderType == ORDER_TYPE_BUY_STOP)
result = ctrade.BuyStop(NormalizeLots(symbol,lots),price,symbol,priceSL,priceTP,ORDER_TIME_GTC,0,comment);
if(result)
{
Sleep(500);
return true;
}
else
{
string err = ctrade.ResultRetcodeDescription();
MessageBox(err,"Operation failed",MB_ICONEXCLAMATION);
return false;
}
}
return false;
}
bool CMarketOrder::PendingLong(ENUM_ORDER_TYPE orderType, string symbol, double lots, double price, double priceSL=0, double priceTP=0, string comment = "")
{
bool result = false;
while(!IsStopped() && !result)
{
//do checks
if(!tradingChecks.OkToOpenPosition(symbol,orderType,lots,price,priceSL,priceTP))
{
Alert("Unable to place trade: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to buy
if(orderType == ORDER_TYPE_BUY_LIMIT)
result = ctrade.BuyLimit(NormalizeLots(symbol,lots),price,symbol,priceSL,priceTP,ORDER_TIME_GTC,0,comment);
else if(orderType == ORDER_TYPE_BUY_STOP)
result = ctrade.BuyStop(NormalizeLots(symbol,lots),price,symbol,priceSL,priceTP,ORDER_TIME_GTC,0,comment);
if(result)
{
Sleep(500);
return true;
}
else
{
string err = ctrade.ResultRetcodeDescription();
MessageBox(err,"Operation failed",MB_ICONEXCLAMATION);
return false;
}
}
return false;
}
bool CMarketOrder::PendingShort(ENUM_ORDER_TYPE orderType, string symbol, double lots, double price, uint stoploss=0,uint takeprofit=0,bool stopsInPips = true, string comment = "")
{
bool result = false;
while(!IsStopped() && !result)
{
double point = SymbolInfoDouble(symbol,SYMBOL_POINT);
//calc SL + TP
double priceSL = (stoploss ? NormalizePrice(symbol,price + stoploss*point) : 0.0);
double priceTP = (takeprofit ? NormalizePrice(symbol,price - takeprofit*point) : 0.0);
//do checks
if(!tradingChecks.OkToOpenPosition(symbol,orderType,lots,price,priceSL,priceTP))
{
Alert("Unable to place trade: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to sell
if(orderType == ORDER_TYPE_SELL_LIMIT)
result = ctrade.SellLimit(NormalizeLots(symbol,lots),price,symbol,priceSL,priceTP,ORDER_TIME_GTC,0,comment);
else if(orderType == ORDER_TYPE_SELL_STOP)
result = ctrade.SellStop(NormalizeLots(symbol,lots),price,symbol,priceSL,priceTP,ORDER_TIME_GTC,0,comment);
if(result)
{
Sleep(500);
return true;
}
else
{
string err = ctrade.ResultRetcodeDescription();
MessageBox(err,"Operation failed",MB_ICONEXCLAMATION);
return false;
}
}
return false;
}
bool CMarketOrder::PendingShort(ENUM_ORDER_TYPE orderType, string symbol, double lots, double price, double priceSL=0, double priceTP=0, string comment = "")
{
bool result = false;
while(!IsStopped() && !result)
{
//do checks
if(!tradingChecks.OkToOpenPosition(symbol,orderType,lots,price,priceSL,priceTP))
{
Alert("Unable to place trade: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to sell
if(orderType == ORDER_TYPE_SELL_LIMIT)
result = ctrade.SellLimit(NormalizeLots(symbol,lots),price,symbol,priceSL,priceTP,ORDER_TIME_GTC,0,comment);
else if(orderType == ORDER_TYPE_SELL_STOP)
result = ctrade.SellStop(NormalizeLots(symbol,lots),price,symbol,priceSL,priceTP,ORDER_TIME_GTC,0,comment);
if(result)
{
Sleep(500);
return true;
}
else
{
string err = ctrade.ResultRetcodeDescription();
MessageBox(err,"Operation failed",MB_ICONEXCLAMATION);
return false;
}
}
return false;
}
bool CMarketOrder::Modify(ulong ticket, bool stopsInPips = true, int stoploss = -1, int takeprofit = -1)
{
if(!PositionSelectByTicket(ticket))
return false;
string symbol = PositionGetString(POSITION_SYMBOL);
double price = PositionGetDouble(POSITION_PRICE_CURRENT);
double _point = SymbolInfoDouble(symbol,SYMBOL_POINT);
double price = PositionGetDouble(POSITION_PRICE_OPEN);
double point = SymbolInfoDouble(symbol,SYMBOL_POINT);
double priceSL;
double priceTP;
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY){
priceSL = (stoploss ? NormalizePrice(symbol,price - stoploss*_point) : PositionGetDouble(POSITION_SL));
priceTP = (takeprofit ? NormalizePrice(symbol,price + takeprofit*_point) : PositionGetDouble(POSITION_TP));
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
priceSL = (stoploss < 0)
? PositionGetDouble(POSITION_SL)
: (stoploss == 0)
? 0
: NormalizePrice(symbol,price - stoploss*point);
priceTP = (takeprofit < 0)
? PositionGetDouble(POSITION_TP)
: (takeprofit == 0)
? 0
: NormalizePrice(symbol,price + takeprofit*point);
// priceSL = (stoploss ? NormalizePrice(symbol,price - stoploss*_point) : PositionGetDouble(POSITION_SL));
// priceTP = (takeprofit ? NormalizePrice(symbol,price + takeprofit*_point) : PositionGetDouble(POSITION_TP));
}
else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL){
priceSL = (stoploss ? NormalizePrice(symbol,price + stoploss*_point) : PositionGetDouble(POSITION_SL));
priceTP = (takeprofit ? NormalizePrice(symbol,price - takeprofit*_point) : PositionGetDouble(POSITION_TP));
else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
{
// priceSL = (stoploss ? NormalizePrice(symbol,price + stoploss*_point) : PositionGetDouble(POSITION_SL));
// priceTP = (takeprofit ? NormalizePrice(symbol,price - takeprofit*_point) : PositionGetDouble(POSITION_TP));
priceSL = (stoploss < 0)
? PositionGetDouble(POSITION_SL)
: (stoploss == 0)
? 0
: NormalizePrice(symbol,price + stoploss*point);
priceTP = (takeprofit < 0)
? PositionGetDouble(POSITION_TP)
: (takeprofit == 0)
? 0
: NormalizePrice(symbol,price - takeprofit*point);
}
else
return false;
@@ -232,15 +475,25 @@ bool CMarketOrder::Modify(ulong ticket, uint stoploss = 0, uint takeprofit = 0)
//there's no change in SL or TP - do nothing!
if (priceSL == PositionGetDouble(POSITION_SL)
&& priceTP == PositionGetDouble(POSITION_TP))
return true;
return false;
bool result = false;
int counter = 0;
while(!IsStopped() && !result)
{
//do checks
if(!tradingChecks.OkToModifyPosition(symbol,ticket,priceSL,priceTP))
{
Print("Unable to modify: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to modify position
result = ctrade.PositionModify(symbol,priceSL,priceTP);
if(_IsNettingAccount())
result = ctrade.PositionModify(symbol,priceSL,priceTP);
else
result = ctrade.PositionModify(ticket,priceSL,priceTP);
if(result)
{
@@ -263,21 +516,167 @@ bool CMarketOrder::Modify(ulong ticket, double priceSL=0,double priceTP=0)
return false;
string symbol = PositionGetString(POSITION_SYMBOL);
double price = PositionGetDouble(POSITION_PRICE_CURRENT);
double _point = SymbolInfoDouble(symbol,SYMBOL_POINT);
double price = PositionGetDouble(POSITION_PRICE_OPEN);
//double point = SymbolInfoDouble(symbol,SYMBOL_POINT);
//there's no change in SL or TP - do nothing!
if (priceSL == PositionGetDouble(POSITION_SL)
&& priceTP == PositionGetDouble(POSITION_TP))
return true;
return false;
bool result = false;
int counter = 0;
while(!IsStopped() && !result)
{
//do checks
if(!tradingChecks.OkToModifyPosition(symbol,ticket,priceSL,priceTP))
{
Print("Unable to modify: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to modify position
result = ctrade.PositionModify(symbol,priceSL,priceTP);
if(_IsNettingAccount())
result = ctrade.PositionModify(symbol,priceSL,priceTP);
else
result = ctrade.PositionModify(ticket,priceSL,priceTP);
if(result)
{
Sleep(500);
return true;
}
else
{
if(!RetryOrderRequest(++counter))
return false;
}
}
return false;
}
bool CMarketOrder::ModifyPending(ulong ticket, double entry, bool stopsInPips = true, int stoploss = -1, int takeprofit = -1, ENUM_ORDER_TYPE_TIME orderTypeTime = ORDER_TIME_GTC, datetime expires = 0)
{
if(!OrderSelect(ticket))
return false;
string symbol = OrderGetString(ORDER_SYMBOL);
double point = SymbolInfoDouble(symbol,SYMBOL_POINT);
if(entry == 0)
entry = OrderGetDouble(ORDER_PRICE_OPEN);
double priceSL;
double priceTP;
if((OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY) ||
(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT) ||
(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP) ||
(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP_LIMIT))
{
priceSL = (stoploss < 0)
? OrderGetDouble(ORDER_SL)
: (stoploss == 0)
? 0
: NormalizePrice(symbol,entry - stoploss*point);
priceTP = (takeprofit < 0)
? OrderGetDouble(ORDER_TP)
: (takeprofit == 0)
? 0
: NormalizePrice(symbol,entry + takeprofit*point);
}
else if((OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL) ||
(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT) ||
(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP) ||
(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP_LIMIT))
{
priceSL = (stoploss < 0)
? OrderGetDouble(ORDER_SL)
: (stoploss == 0)
? 0
: NormalizePrice(symbol,entry + stoploss*point);
priceTP = (takeprofit < 0)
? OrderGetDouble(ORDER_TP)
: (takeprofit == 0)
? 0
: NormalizePrice(symbol,entry - takeprofit*point);
}
else
return false;
//there's no change in parameters - do nothing!
if (priceSL == OrderGetDouble(ORDER_SL)
&& priceTP == OrderGetDouble(ORDER_TP)
&& entry == OrderGetDouble(ORDER_PRICE_OPEN)
&& orderTypeTime == OrderGetInteger(ORDER_TYPE_TIME)
&& expires == OrderGetInteger(ORDER_TIME_EXPIRATION))
return false;
bool result = false;
int counter = 0;
while(!IsStopped() && !result)
{
//do checks
if(!tradingChecks.OkToModifyOrder(symbol,ticket,entry,priceSL,priceTP))
{
Print("Unable to modify: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to modify position
result = ctrade.OrderModify(ticket,entry,priceSL,priceTP,orderTypeTime,expires);
if(result)
{
Sleep(500);
return true;
}
else
{
if(!RetryOrderRequest(++counter))
return false;
}
}
return false;
}
bool CMarketOrder::ModifyPending(ulong ticket, double entry, double priceSL=0, double priceTP=0, ENUM_ORDER_TYPE_TIME orderTypeTime = ORDER_TIME_GTC, datetime expires = 0)
{
if(!OrderSelect(ticket))
return false;
string symbol = OrderGetString(ORDER_SYMBOL);
if(entry == 0)
entry = OrderGetDouble(ORDER_PRICE_OPEN);
//there's no change in parameters - do nothing!
if (priceSL == OrderGetDouble(ORDER_SL)
&& priceTP == OrderGetDouble(ORDER_TP)
&& entry == OrderGetDouble(ORDER_PRICE_OPEN)
&& orderTypeTime == OrderGetInteger(ORDER_TYPE_TIME)
&& expires == OrderGetInteger(ORDER_TIME_EXPIRATION))
return false;
bool result = false;
int counter = 0;
while(!IsStopped() && !result)
{
//do checks
if(!tradingChecks.OkToModifyOrder(symbol,ticket,entry,priceSL,priceTP))
{
Print("Unable to modify: "+tradingChecks.GetCheckErrorToString());
return false;
}
//attempt to modify position
result = ctrade.OrderModify(ticket,entry,priceSL,priceTP,orderTypeTime,expires);
if(result)
{
@@ -350,6 +749,11 @@ bool CMarketOrder::ClosePartial(ulong ticket, double lots)
return false;
}
bool CMarketOrder::Delete(ulong ticket)
{
return ctrade.OrderDelete(ticket);
}
bool CMarketOrder::Reverse(ulong ticket,double lots = 0, uint stoploss=0, uint takeprofit=0)
{
if(!PositionSelectByTicket(ticket))
@@ -420,6 +824,44 @@ bool CMarketOrder::IsOpen(ulong &ticket, string symbol, long magicNumber = 0)
return this._IsOpen(ticket,symbol,magicNumber);
}
bool CMarketOrder::CloseAll(string symbol = "")
{
int positions=PositionsTotal();
ulong ticketsToClose[];
int ticketsToCloseCounter = 0;
if(positions > 0)
ArrayResize(ticketsToClose,positions);
else
return false;
for(int i=0;i<positions;i++)
{
// ResetLastError();
ulong _ticket=PositionGetTicket(i);
if(_ticket!=0)
{
if(PositionSelectByTicket(_ticket))
{
if((PositionGetString(POSITION_SYMBOL) == symbol) || (symbol == ""))
{
ticketsToClose[ticketsToCloseCounter] = _ticket;
ticketsToCloseCounter++;
}
}
}
}
ArrayResize(ticketsToClose,ticketsToCloseCounter);
for(int i=0;i<ticketsToCloseCounter;i++)
{
this.Close(ticketsToClose[i]);
}
return true;
}
bool CMarketOrder::IsOpen(ulong &ticket,ENUM_POSITION_TYPE &type,string symbol,long magicNumber=0)
{
int positions=PositionsTotal();
@@ -458,6 +900,15 @@ bool CMarketOrder::IsOpen(ulong &ticket,ENUM_POSITION_TYPE &type,string symbol,l
}
bool CMarketOrder::GetPositionType(ulong ticket, ENUM_POSITION_TYPE &_pType)
{
if(!PositionSelectByTicket(ticket))
return false;
_pType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
return true;
}
bool CMarketOrder::_IsOpen(ulong &ticket, string symbol, ENUM_POSITION_TYPE type, long magicNumber)
{
int positions=PositionsTotal();
@@ -546,8 +997,43 @@ string CMarketOrder::PositionTypeToString(ENUM_POSITION_TYPE t)
return "-";
}
string CMarketOrder::OrderTypeToString(ENUM_ORDER_TYPE t)
{
if(t == ORDER_TYPE_BUY)
return "Buy";
else if(t == ORDER_TYPE_BUY_LIMIT)
return "Buy Limit";
else if(t == ORDER_TYPE_BUY_STOP)
return "Buy Stop";
else if(t == ORDER_TYPE_BUY_STOP_LIMIT)
return "Buy Stop Limit";
else if(t == ORDER_TYPE_SELL)
return "Sell";
else if(t == ORDER_TYPE_SELL_LIMIT)
return "Sell Limit";
else if(t == ORDER_TYPE_SELL_STOP)
return "Sell Stop";
else if(t == ORDER_TYPE_SELL_STOP_LIMIT)
return "Sell Stop Limit";
else
return "-";
}
ENUM_ORDER_TYPE CMarketOrder::TradeBias(ENUM_ORDER_TYPE t)
{
if((t == ORDER_TYPE_BUY) ||
(t == ORDER_TYPE_BUY_LIMIT) ||
(t == ORDER_TYPE_BUY_STOP) ||
(t == ORDER_TYPE_BUY_STOP_LIMIT))
return ORDER_TYPE_BUY;
else
return ORDER_TYPE_SELL;
}
bool CMarketOrder::RetryOrderRequest(int retryNumber)
{
Print(ctrade.ResultRetcodeDescription());
if(retryNumber >= this.numberOfRetries)
{
PrintFormat("Giving up on maximum number of retries (%d)",this.numberOfRetries);
@@ -575,37 +1061,16 @@ bool CMarketOrder::RetryOrderRequest(int retryNumber)
break;
default:
MessageBox(ctrade.ResultRetcodeDescription(),"Operation failed",MB_ICONEXCLAMATION);
return false;
}
}
//+------------------------------------------------------------------+
//| Normalizing |
//+------------------------------------------------------------------+
double NormalizeLots(string symbol, double InputLots)
void CMarketOrder::SetTradeId(ulong tradeId)
{
double lotsMin = SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
double lotsMax = SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
int lotsDigits = (int) - MathLog10(SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP));
if(InputLots < lotsMin)
InputLots = lotsMin;
if(InputLots > lotsMax)
InputLots = lotsMax;
return NormalizeDouble(InputLots, lotsDigits);
ctrade.SetExpertMagicNumber(tradeId);
}
double NormalizePrice(string symbol, double price, double tick = 0)
{
double _tick = tick ? tick : SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE);
int _digits = (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
if (tick)
return NormalizeDouble(MathRound(price/_tick)*_tick,_digits);
else
return NormalizeDouble(price,_digits);
}
+932
View File
@@ -0,0 +1,932 @@
//
// Copyright 2018, Artur Zas
// https://www.az-invest.eu
// https://www.mql5.com/en/users/arturz
//
#ifdef __MQL5__
//--- class for performing trade operations
#include <Trade\Trade.mqh>
CTrade trade;
//--- class for working with orders
#include <Trade\OrderInfo.mqh>
COrderInfo orderinfo;
//--- class for working with positions
#include <Trade\PositionInfo.mqh>
CPositionInfo positioninfo;
//--- introduce the predefined variables from MQL4 for versatility of the code
#define Ask SymbolInfoDouble(_symbol,SYMBOL_ASK)
#define Bid SymbolInfoDouble(_symbol,SYMBOL_BID)
bool suppressLogOutput = false;
void SuppressGlobalLogOutput() { suppressLogOutput = true; };
#endif
#define _point SymbolInfoDouble(_symbol,SYMBOL_POINT)
//--- redefine the order types from MQL5 to MQL4 for use in common code
#ifdef __MQL4__
#define ORDER_TYPE_BUY OP_BUY
#define ORDER_TYPE_SELL OP_SELL
#define ORDER_TYPE_BUY_LIMIT OP_BUYLIMIT
#define ORDER_TYPE_SELL_LIMIT OP_SELLLIMIT
#define ORDER_TYPE_BUY_STOP OP_BUYSTOP
#define ORDER_TYPE_SELL_STOP OP_SELLSTOP
#endif
enum ENUM_TC_ERROR
{
tcErrorNONE = 0,
tcErrorNotEnoughMoney,
tcErrorInvalidStops,
tcErrorOrderLimitReached,
tcErrorFreezeLevel,
tcErrorNothingChanged,
tcErrorInvalidPrice,
};
class CTradingChecks
{
private:
ENUM_TC_ERROR _err;
bool _suppressLogOutput;
public:
CTradingChecks();
~CTradingChecks();
string GetCheckErrorToString();
void SuppressLogOutput() { _suppressLogOutput = true; };
bool OkToOpenOrder(string _symbol,ENUM_ORDER_TYPE type, double lots, double entryPrice, double sl, double tp);
bool OkToModifyOrder(string _symbol,ulong ticket,double price, double sl, double tp);
#ifdef __MQL5__
bool OkToOpenPosition(string _symbol,ENUM_ORDER_TYPE type, double lots, double entryPrice, double sl, double tp);
bool OkToModifyPosition(string _symbol,ulong ticket, double sl, double tp);
#endif
};
CTradingChecks::CTradingChecks(void)
{
suppressLogOutput = false;
}
CTradingChecks::~CTradingChecks(void)
{
}
string CTradingChecks::GetCheckErrorToString(void)
{
switch(_err)
{
case tcErrorNONE:
return "No Error";
case tcErrorNotEnoughMoney:
return "Not enough money (check previous message in Experts log)";
case tcErrorInvalidStops:
return "Invalid stops (check previous message in Experts log)";
case tcErrorOrderLimitReached:
return "Maximum order limit reached";
case tcErrorFreezeLevel:
return "Freeze level (check previous message in Experts log)";
case tcErrorNothingChanged:
return "Nothing to change";
case tcErrorInvalidPrice:
return "Invalid entry price for this order type";
default:
return "";
}
}
bool CTradingChecks::OkToOpenOrder(string _symbol,ENUM_ORDER_TYPE type, double lots, double entryPrice,double sl, double tp)
{
if(!IsNewPendingOrderAllowed())
{
_err = tcErrorOrderLimitReached;
return false;
}
if(!CheckStopLoss_Takeprofit(_symbol,type,entryPrice,sl,tp))
{
_err = tcErrorInvalidStops;
return false;
}
_err = tcErrorNONE;
return true;
}
#ifdef __MQL5__
bool CTradingChecks::OkToOpenPosition(string _symbol,ENUM_ORDER_TYPE type, double lots, double entryPrice,double sl, double tp)
{
#ifdef __MQL5__
if(!CheckMoneyForTrade(_symbol,lots,type))
{
_err = tcErrorNotEnoughMoney;
return false;
}
// if(NewOrderAllowedVolume(_symbol) < lots)
// return false;
#else
if(!CheckMoneyForTrade(_symbol,lots,(int)type))
{
_err = tcErrorNotEnoughMoney;
return false;
}
if(!IsNewPendingOrderAllowed())
{
_err = tcErrorOrderLimitReached;
return false;
}
#endif
if(!CheckStopLoss_Takeprofit(_symbol,type,entryPrice,sl,tp))
{
_err = tcErrorInvalidStops;
return false;
}
_err = tcErrorNONE;
return true;
}
#endif;
bool CTradingChecks::OkToModifyOrder(string _symbol, ulong ticket,double price, double sl, double tp)
{
#ifdef __MQL5__
if(!OrderModifyCheck(ticket,price,sl,tp))
{
_err = tcErrorNothingChanged;
return false;
}
if(!CheckOrderForFREEZE_LEVEL(_symbol,ticket))
{
_err = tcErrorFreezeLevel;
return false;
}
#else
if(!OrderModifyCheck((int)ticket,price,sl,tp))
{
_err = tcErrorNothingChanged;
return false;
}
if(!CheckOrderForFREEZE_LEVEL(_symbol,(int)ticket))
{
_err = tcErrorFreezeLevel;
return false;
}
#endif
if(!CheckPendingOrderEntryChange(_symbol,ticket,price))
{
_err = tcErrorInvalidPrice;
return false;
}
_err = tcErrorNONE;
return true;
}
#ifdef __MQL5__
bool CTradingChecks::OkToModifyPosition(string _symbol, ulong ticket,double sl,double tp)
{
if(!PositionModifyCheck(ticket,sl,tp))
{
_err = tcErrorNothingChanged;
return false;
}
if(!CheckPositionForFREEZE_LEVEL(_symbol,ticket))
{
_err = tcErrorFreezeLevel;
return false;
}
_err = tcErrorNONE;
return true;
}
#endif
//////////////////////////////////////////////////////////////////
//
// Helper functions from https://www.mql5.com/en/articles/2555
//
///////////////////////////////////////////////////////////////////
#ifdef __MQL5__
bool CheckMoneyForTrade(string symb,double lots,ENUM_ORDER_TYPE type)
{
//--- Getting the opening price
MqlTick mqltick;
SymbolInfoTick(symb,mqltick);
double price=mqltick.ask;
if(type==ORDER_TYPE_SELL)
price=mqltick.bid;
//--- values of the required and free margin
double margin,free_margin=AccountInfoDouble(ACCOUNT_MARGIN_FREE);
//--- call of the checking function
if(!OrderCalcMargin(type,symb,lots,price,margin))
{
//--- something went wrong, report and return false
if(suppressLogOutput == false)
{
Print("Error in ",__FUNCTION__," code=",GetLastError());
}
return(false);
}
//--- if there are insufficient funds to perform the operation
if(margin>free_margin)
{
//--- report the error and return false
if(suppressLogOutput == false)
{
Print("Not enough money for ",EnumToString(type)," ",lots," ",symb," Error code=",GetLastError());
Print("Required margin:"+DoubleToString(margin,2)+"; free margin:"+DoubleToString(free_margin,2));
}
return(false);
}
//--- checking successful
return(true);
}
#else
bool CheckMoneyForTrade(string symb, double lots,int type)
{
double free_margin=AccountFreeMarginCheck(symb,type, lots);
//-- if there is not enough money
if(free_margin<0)
{
string oper=(type==OP_BUY)? "Buy":"Sell";
if(suppressLogOutput == false)
{
Print("Not enough money for ", oper," ",lots, " ", symb, " Error code=",GetLastError());
}
return(false);
}
//--- checking successful
return(true);
}
#endif
//+------------------------------------------------------------------+
//| Check if another order can be placed |
//+------------------------------------------------------------------+
bool IsNewPendingOrderAllowed()
{
//--- get the number of pending orders allowed on the account
int max_allowed_orders=(int)AccountInfoInteger(ACCOUNT_LIMIT_ORDERS);
//--- if there is no limitation, return true; you can send an order
if(max_allowed_orders==0) return(true);
//--- if we passed to this line, then there is a limitation; find out how many orders are already placed
int orders=OrdersTotal();
//--- return the result of comparing
return(orders<max_allowed_orders);
}
#ifdef __MQL5__
//+------------------------------------------------------------------+
//| Return the size of position on the specified symbol |
//+------------------------------------------------------------------+
double PositionVolume(string symbol)
{
//--- try to select position by a symbol
bool selected=PositionSelect(symbol);
//--- there is a position
if(selected)
//--- return volume of the position
return(PositionGetDouble(POSITION_VOLUME));
else
{
//--- report a failure to select position
if(suppressLogOutput == false)
{
Print(__FUNCTION__," Failed to perform PositionSelect() for symbol ",
symbol," Error ",GetLastError());
}
return(-1);
}
}
//+------------------------------------------------------------------+
//| returns the volume of current pending order by a symbol |
//+------------------------------------------------------------------+
double PendingsVolume(string symbol)
{
double volume_on_symbol=0;
ulong ticket;
//--- get the number of all currently placed orders by all symbols
int all_orders=OrdersTotal();
//--- get over all orders in the loop
for(int i=0;i<all_orders;i++)
{
//--- get the ticket of an order by its position in the list
ticket = OrderGetTicket(i);
if((bool)ticket)
{
//--- if our symbol is specified in the order, add the volume of this order
if(symbol==OrderGetString(ORDER_SYMBOL))
volume_on_symbol+=OrderGetDouble(ORDER_VOLUME_INITIAL);
}
}
//--- return the total volume of currently placed pending orders for a specified symbol
return(volume_on_symbol);
}
//+------------------------------------------------------------------+
//| Return the maximum allowed volume for an order on the symbol |
//+------------------------------------------------------------------+
double NewOrderAllowedVolume(string symbol)
{
double allowed_volume=0;
//--- get the limitation on the maximal volume of an order
double symbol_max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
//--- get the limitation on the volume by a symbol
double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_LIMIT);
//--- get the volume of the open position by a symbol
double opened_volume=PositionVolume(symbol);
if(opened_volume>=0)
{
//--- if we have exhausted the volume
if(max_volume-opened_volume<=0)
return(0);
//--- volume of the open position doesn't exceed max_volume
double orders_volume_on_symbol=PendingsVolume(symbol);
allowed_volume=max_volume-opened_volume-orders_volume_on_symbol;
if(allowed_volume>symbol_max_volume) allowed_volume=symbol_max_volume;
}
return(allowed_volume);
}
#endif
//+------------------------------------------------------------------+
//| Check the correctness of StopLoss and TakeProfit |
//+------------------------------------------------------------------+
bool CheckStopLoss_Takeprofit(string _symbol, ENUM_ORDER_TYPE type,double price,double SL,double TP)
{
//--- get the SYMBOL_TRADE_STOPS_LEVEL level
int stops_level=(int)SymbolInfoInteger(_symbol,SYMBOL_TRADE_STOPS_LEVEL);
if(stops_level!=0)
{
if(suppressLogOutput == false)
{
PrintFormat("SYMBOL_TRADE_STOPS_LEVEL=%d: StopLoss and TakeProfit must"+
" not be nearer than %d points from the closing price",stops_level,stops_level);
}
}
//---
bool SL_check=false,TP_check=false;
//--- check the order type
switch(type)
{
//--- Buy operation
case ORDER_TYPE_BUY:
{
//--- check the StopLoss
SL_check= (SL==0) ? true : (Bid-SL>stops_level*_point);
if(!SL_check && suppressLogOutput == false)
PrintFormat("For order %s StopLoss=%.5f must be less than %.5f"+
" (Bid=%.5f - SYMBOL_TRADE_STOPS_LEVEL=%d points)",
EnumToString(type),SL,Bid-stops_level*_point,Bid,stops_level);
//--- check the TakeProfit
TP_check= (TP==0) ? true : (TP-Bid>stops_level*_point);
if(!TP_check && suppressLogOutput == false)
PrintFormat("For order %s TakeProfit=%.5f must be greater than %.5f"+
" (Bid=%.5f + SYMBOL_TRADE_STOPS_LEVEL=%d points)",
EnumToString(type),TP,Bid+stops_level*_point,Bid,stops_level);
//--- return the result of checking
return(SL_check&&TP_check);
}
//--- Sell operation
case ORDER_TYPE_SELL:
{
//--- check the StopLoss
SL_check= (SL==0) ? true : (SL-Ask>stops_level*_point);
if(!SL_check && suppressLogOutput == false)
PrintFormat("For order %s StopLoss=%.5f must be greater than %.5f"+
" (Ask=%.5f + SYMBOL_TRADE_STOPS_LEVEL=%d points)",
EnumToString(type),SL,Ask+stops_level*_point,Ask,stops_level);
//--- check the TakeProfit
TP_check= (TP==0) ? true : (Ask-TP>stops_level*_point);
if(!TP_check && suppressLogOutput == false)
PrintFormat("For order %s TakeProfit=%.5f must be less than %.5f"+
" (Ask=%.5f - SYMBOL_TRADE_STOPS_LEVEL=%d points)",
EnumToString(type),TP,Ask-stops_level*_point,Ask,stops_level);
//--- return the result of checking
return(TP_check&&SL_check);
}
break;
//--- BuyLimit pending order
case ORDER_TYPE_BUY_LIMIT:
{
//--- check the StopLoss
SL_check= (SL==0) ? true : ((price-SL)>stops_level*_point);
if(!SL_check && suppressLogOutput == false)
PrintFormat("For order %s StopLoss=%.5f must be less than %.5f"+
" (Open-StopLoss=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
EnumToString(type),SL,price-stops_level*_point,(int)((price-SL)/_point),stops_level);
//--- check the TakeProfit
TP_check= (TP==0) ? true : ((TP-price)>stops_level*_point);
if(!TP_check && suppressLogOutput == false)
PrintFormat("For order %s TakeProfit=%.5f must be greater than %.5f"+
" (TakeProfit-Open=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
EnumToString(type),TP,price+stops_level*_point,(int)((TP-price)/_point),stops_level);
//--- return the result of checking
return(SL_check&&TP_check);
}
//--- SellLimit pending order
case ORDER_TYPE_SELL_LIMIT:
{
//--- check the StopLoss
SL_check= (SL==0) ? true : ((SL-price)>stops_level*_point);
if(!SL_check && suppressLogOutput == false)
PrintFormat("For order %s StopLoss=%.5f must be greater than %.5f"+
" (StopLoss-Open=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
EnumToString(type),SL,price+stops_level*_point,(int)((SL-price)/_point),stops_level);
//--- check the TakeProfit
TP_check= (TP==0) ? true : ((price-TP)>stops_level*_point);
if(!TP_check && suppressLogOutput == false)
PrintFormat("For order %s TakeProfit=%.5f must be less than %.5f"+
" (Open-TakeProfit=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
EnumToString(type),TP,price-stops_level*_point,(int)((price-TP)/_point),stops_level);
//--- return the result of checking
return(TP_check&&SL_check);
}
break;
//--- BuyStop pending order
case ORDER_TYPE_BUY_STOP:
{
//--- check the StopLoss
SL_check= (SL==0) ? true : ((price-SL)>stops_level*_point);
if(!SL_check && suppressLogOutput == false)
PrintFormat("For order %s StopLoss=%.5f must be less than %.5f"+
" (Open-StopLoss=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
EnumToString(type),SL,price-stops_level*_point,(int)((price-SL)/_point),stops_level);
//--- check the TakeProfit
TP_check= (TP==0) ? true : ((TP-price)>stops_level*_point);
if(!TP_check && suppressLogOutput == false)
PrintFormat("For order %s TakeProfit=%.5f must be greater than %.5f"+
" (TakeProfit-Open=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
EnumToString(type),TP,price-stops_level*_point,(int)((TP-price)/_point),stops_level);
//--- return the result of checking
return(SL_check&&TP_check);
}
//--- SellStop pending order
case ORDER_TYPE_SELL_STOP:
{
//--- check the StopLoss
SL_check= (SL==0) ? true : ((SL-price)>stops_level*_point);
if(!SL_check && suppressLogOutput == false)
PrintFormat("For order %s StopLoss=%.5f must be greater than %.5f"+
" (StopLoss-Open=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
EnumToString(type),SL,price+stops_level*_point,(int)((SL-price)/_point),stops_level);
//--- check the TakeProfit
TP_check= (TP==0) ? true : ((price-TP)>stops_level*_point);
if(!TP_check && suppressLogOutput == false)
PrintFormat("For order %s TakeProfit=%.5f must be less than %.5f"+
" (Open-TakeProfit=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
EnumToString(type),TP,price-stops_level*_point,(int)((price-TP)/_point),stops_level);
//--- return the result of checking
return(TP_check&&SL_check);
}
break;
}
//---
return false;
}
#ifdef __MQL5__
//+------------------------------------------------------------------+
//| Checking the new values of levels before order modification |
//+------------------------------------------------------------------+
bool OrderModifyCheck(ulong ticket,double price,double sl,double tp)
{
//--- select order by ticket
if(orderinfo.Select(ticket))
{
//--- point size and name of the symbol, for which a pending order was placed
string symbol=orderinfo.Symbol();
double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
int digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
//--- check if there are changes in the Open price
bool PriceOpenChanged=(MathAbs(orderinfo.PriceOpen()-price)>point);
//--- check if there are changes in the StopLoss level
bool StopLossChanged=(MathAbs(orderinfo.StopLoss()-sl)>point);
//--- check if there are changes in the Takeprofit level
bool TakeProfitChanged=(MathAbs(orderinfo.TakeProfit()-tp)>point);
//--- if there are any changes in levels
if(PriceOpenChanged || StopLossChanged || TakeProfitChanged)
return(true); // order can be modified
//--- there are no changes in the Open, StopLoss and Takeprofit levels
else
{
//--- notify about the error
if(suppressLogOutput == false)
{
PrintFormat("Order #%d already has levels of Open=%.5f SL=%.5f TP=%.5f",
ticket,orderinfo.PriceOpen(),orderinfo.StopLoss(),orderinfo.TakeProfit());
}
}
}
//--- came to the end, no changes for the order
return(false); // no point in modifying
}
//+------------------------------------------------------------------+
//| Checking the new values of levels before order modification |
//+------------------------------------------------------------------+
bool PositionModifyCheck(ulong ticket,double sl,double tp)
{
//--- select order by ticket
if(positioninfo.SelectByTicket(ticket))
{
//--- point size and name of the symbol, for which a pending order was placed
string symbol=positioninfo.Symbol();
double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
//--- check if there are changes in the StopLoss level
bool StopLossChanged=(MathAbs(positioninfo.StopLoss()-sl)>point);
//--- check if there are changes in the Takeprofit level
bool TakeProfitChanged=(MathAbs(positioninfo.TakeProfit()-tp)>point);
//--- if there are any changes in levels
if(StopLossChanged || TakeProfitChanged)
return(true); // position can be modified
//--- there are no changes in the StopLoss and Takeprofit levels
else
{
//--- notify about the error
if(suppressLogOutput == false)
{
PrintFormat("Order #%d already has levels of Open=%.5f SL=%.5f TP=%.5f",
ticket,orderinfo.PriceOpen(),orderinfo.StopLoss(),orderinfo.TakeProfit());
}
}
}
//--- came to the end, no changes for the order
return(false); // no point in modifying
}
#else
//+------------------------------------------------------------------+
//| Checking the new values of levels before order modification |
//+------------------------------------------------------------------+
bool OrderModifyCheck(int ticket,double price,double sl,double tp)
{
//--- select order by ticket
if(OrderSelect(ticket,SELECT_BY_TICKET))
{
//--- point size and name of the symbol, for which a pending order was placed
string symbol=OrderSymbol();
double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
//--- check if there are changes in the Open price
bool PriceOpenChanged=true;
int type=OrderType();
if(!(type==OP_BUY || type==OP_SELL))
{
PriceOpenChanged=(MathAbs(OrderOpenPrice()-price)>point);
}
//--- check if there are changes in the StopLoss level
bool StopLossChanged=(MathAbs(OrderStopLoss()-sl)>point);
//--- check if there are changes in the Takeprofit level
bool TakeProfitChanged=(MathAbs(OrderTakeProfit()-tp)>point);
//--- if there are any changes in levels
if(PriceOpenChanged || StopLossChanged || TakeProfitChanged)
return(true); // order can be modified
//--- there are no changes in the Open, StopLoss and Takeprofit levels
else
{
//--- notify about the error
if(suppressLogOutput == false)
{
PrintFormat("Order #%d already has levels of Open=%.5f SL=%.5f TP=%.5f",
ticket,OrderOpenPrice(),OrderStopLoss(),OrderTakeProfit());
}
}
}
//--- came to the end, no changes for the order
return(false); // no point in modifying
}
#endif
#ifdef __MQL5__
//+------------------------------------------------------------------+
//| Check the distance from opening price to activation price |
//+------------------------------------------------------------------+
bool CheckOrderForFREEZE_LEVEL(string _symbol, ulong ticket)
{
//--- get the SYMBOL_TRADE_FREEZE_LEVEL level
int freeze_level=(int)SymbolInfoInteger(_symbol,SYMBOL_TRADE_FREEZE_LEVEL);
if(freeze_level!=0)
{
if(suppressLogOutput == false)
{
PrintFormat("SYMBOL_TRADE_FREEZE_LEVEL=%d: Cannot modify order"+
" nearer than %d points from the activation price",freeze_level,freeze_level);
}
}
//--- select order for working
if(!OrderSelect(ticket))
{
//--- failed to select order
return(false);
}
//--- get the order data
double price=OrderGetDouble(ORDER_PRICE_OPEN);
double sl=OrderGetDouble(ORDER_SL);
double tp=OrderGetDouble(ORDER_TP);
ENUM_ORDER_TYPE type=(ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
//--- result of checking
bool check=false;
//--- check the order type
switch(type)
{
//--- BuyLimit pending order
case ORDER_TYPE_BUY_LIMIT:
{
//--- check the distance from the opening price to the activation price
check=((Ask-price)>freeze_level*_point);
if(!check && suppressLogOutput == false)
PrintFormat("Order %s #%d cannot be modified: Ask-Open=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
EnumToString(type),ticket,(int)((Ask-price)/_point),freeze_level);
return(check);
}
//--- BuyLimit pending order
case ORDER_TYPE_SELL_LIMIT:
{
//--- check the distance from the opening price to the activation price
check=((price-Bid)>freeze_level*_point);
if(!check && suppressLogOutput == false)
PrintFormat("Order %s #%d cannot be modified: Open-Bid=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
EnumToString(type),ticket,(int)((price-Bid)/_point),freeze_level);
return(check);
}
break;
//--- BuyStop pending order
case ORDER_TYPE_BUY_STOP:
{
//--- check the distance from the opening price to the activation price
check=((price-Ask)>freeze_level*_point);
if(!check && suppressLogOutput == false)
PrintFormat("Order %s #%d cannot be modified: Ask-Open=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
EnumToString(type),ticket,(int)((price-Ask)/_point),freeze_level);
return(check);
}
//--- SellStop pending order
case ORDER_TYPE_SELL_STOP:
{
//--- check the distance from the opening price to the activation price
check=((Bid-price)>freeze_level*_point);
if(!check && suppressLogOutput == false)
PrintFormat("Order %s #%d cannot be modified: Bid-Open=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
EnumToString(type),ticket,(int)((Bid-price)/_point),freeze_level);
return(check);
}
break;
}
//--- order did not pass the check
return (false);
}
//+------------------------------------------------------------------+
//| Check if the TP and SL are too close to activation price |
//+------------------------------------------------------------------+
bool CheckPositionForFREEZE_LEVEL(string _symbol, ulong ticket)
{
//--- get the SYMBOL_TRADE_FREEZE_LEVEL level
int freeze_level=(int)SymbolInfoInteger(_symbol,SYMBOL_TRADE_FREEZE_LEVEL);
if(freeze_level!=0 && suppressLogOutput == false)
{
PrintFormat("SYMBOL_TRADE_FREEZE_LEVEL=%d: Cannot modify order"+
" nearer than %d points from the activation price",freeze_level,freeze_level);
}
//--- select position for working
if(!PositionSelectByTicket(ticket))
{
//--- failed to select position
return(false);
}
//--- get the order data
ENUM_POSITION_TYPE pos_type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
double sl=PositionGetDouble(POSITION_SL);
double tp=PositionGetDouble(POSITION_TP);
//--- result of checking StopLoss and TakeProfit
bool SL_check=false,TP_check=false;
//--- position type
switch(pos_type)
{
//--- buy
case POSITION_TYPE_BUY:
{
SL_check=(sl == 0) ? true: (Bid-sl>freeze_level*_point);
if(!SL_check && suppressLogOutput == false)
PrintFormat("Position %s #%d cannot be modified: Bid-StopLoss=%d points"+
" < SYMBOL_TRADE_FREEZE_LEVEL=%d points)",
EnumToString(pos_type),ticket,(int)((Bid-sl)/_point),freeze_level);
TP_check=(tp == 0) ? true: (tp-Bid>freeze_level*_point);
if(!TP_check && suppressLogOutput == false)
PrintFormat("Position %s #%d cannot be modified: TakeProfit-Bid=%d points"+
" < SYMBOL_TRADE_FREEZE_LEVEL=%d points)",
EnumToString(pos_type),ticket,(int)((tp-Bid)/_point),freeze_level);
//--- return the result of checking
return(SL_check&&TP_check);
}
break;
//--- sell
case POSITION_TYPE_SELL:
{
SL_check=(sl == 0) ? true: (sl-Ask>freeze_level*_point);
if(!SL_check && suppressLogOutput == false)
PrintFormat("Position %s cannot be modified: StopLoss-Ask=%d points"+
" < SYMBOL_TRADE_FREEZE_LEVEL=%d points)",
EnumToString(pos_type),(int)((sl-Ask)/_point),freeze_level);
TP_check=(tp == 0) ? true: (Ask-tp>freeze_level*_point);
if(!TP_check && suppressLogOutput == false)
PrintFormat("Position %s cannot be modified: Ask-TakeProfit=%d points"+
" < SYMBOL_TRADE_FREEZE_LEVEL=%d points)",
EnumToString(pos_type),(int)((Ask-tp)/_point),freeze_level);
//--- return the result of checking
return(SL_check&&TP_check);
}
break;
}
//--- position did not pass the check
return (false);
}
#else
bool CheckOrderForFREEZE_LEVEL(string _symbol,int ticket)
{
//--- get the SYMBOL_TRADE_FREEZE_LEVEL level
int freeze_level=(int)SymbolInfoInteger(_symbol,SYMBOL_TRADE_FREEZE_LEVEL);
if(freeze_level!=0 && suppressLogOutput == false)
{
PrintFormat("SYMBOL_TRADE_FREEZE_LEVEL=%d: Cannot modify order"+
" nearer than %d points from the activation price",freeze_level,freeze_level);
}
//--- select order for working
if(!OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
{
//--- failed to select order
return (false);
}
//--- get the order data
double price=OrderOpenPrice();
double sl=OrderStopLoss();
double tp=OrderTakeProfit();
int type=OrderType();
//--- result of checking
bool check=false;
//--- check the order type
switch(type)
{
//--- BuyLimit pending order
case OP_BUYLIMIT:
{
//--- check the distance from the opening price to the activation price
check=((Ask-price)>freeze_level*_point);
if(!check && suppressLogOutput == false)
PrintFormat("Order OP_BUYLIMIT #%d cannot be modified: Ask-Open=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
ticket,(int)((Ask-price)/_point),freeze_level);
return(check);
}
//--- BuyLimit pending order
case OP_SELLLIMIT:
{
//--- check the distance from the opening price to the activation price
check=((price-Bid)>freeze_level*_point);
if(!check && suppressLogOutput == false)
PrintFormat("Order OP_SELLLIMIT #%d cannot be modified: Open-Bid=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
ticket,(int)((price-Bid)/_point),freeze_level);
return(check);
}
break;
//--- BuyStop pending order
case OP_BUYSTOP:
{
//--- check the distance from the opening price to the activation price
check=((price-Ask)>freeze_level*_point);
if(!check && suppressLogOutput == false)
PrintFormat("Order OP_BUYSTOP #%d cannot be modified: Ask-Open=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
ticket,(int)((price-Ask)/_point),freeze_level);
return(check);
}
//--- SellStop pending order
case OP_SELLSTOP:
{
//--- check the distance from the opening price to the activation price
check=((Bid-price)>freeze_level*_point);
if(!check && suppressLogOutput == false)
PrintFormat("Order OP_SELLSTOP #%d cannot be modified: Bid-Open=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
ticket,(int)((Bid-price)/_point),freeze_level);
return(check);
}
break;
//--- checking opened Buy order
case OP_BUY:
{
//--- check TakeProfit distance to the activation price
bool TP_check=(tp == 0) ? true: (tp-Bid>freeze_level*_point);
if(!TP_check && suppressLogOutput == false)
PrintFormat("Order OP_BUY %d cannot be modified: TakeProfit-Bid=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
ticket,(int)((tp-Bid)/_point),freeze_level);
//--- check TakeProfit distance to the activation price
bool SL_check=(sl == 0) ? true: (Bid-sl>freeze_level*_point);
if(!SL_check && suppressLogOutput == false)
PrintFormat("Order OP_BUY %d cannot be modified: TakeProfit-Bid=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
ticket,(int)((Bid-sl)/_point),freeze_level);
return(SL_check&&TP_check);
}
break;
//--- checking opened Sell order
case OP_SELL:
{
//--- check TakeProfit distance to the activation price
bool TP_check=(tp == 0) ? true: (Ask-tp>freeze_level*_point);
if(!TP_check && suppressLogOutput == false)
PrintFormat("Order OP_SELL %d cannot be modified: Ask-TakeProfit=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
ticket,(int)((Ask-tp)/_point),freeze_level);
//--- check TakeProfit distance to the activation price
bool SL_check=(sl == 0) ? true: (sl-Ask>freeze_level*_point);
if(!SL_check && suppressLogOutput == false)
PrintFormat("Order OP_BUY %d cannot be modified: TakeProfit-Bid=%d points < SYMBOL_TRADE_FREEZE_LEVEL=%d points",
ticket,(int)((sl-Ask)/_point),freeze_level);
return(SL_check&&TP_check);
}
break;
}
//--- order did not pass the check
return (false);
}
#endif
bool CheckPendingOrderEntryChange(string _symbol, ulong ticket, double newEntryPrice)
{
//--- select order for working
if(!OrderSelect(ticket))
{
//--- failed to select order
return(false);
}
//--- get the order data
ENUM_ORDER_TYPE type=(ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
//--- result of checking
bool check=false;
//--- check the order type
switch(type)
{
//--- BuyLimit pending order
case ORDER_TYPE_BUY_LIMIT:
{
//--- check the distance from the opening price to the activation price
check= (newEntryPrice < Ask);
if(!check && suppressLogOutput == false)
PrintFormat("Order %s #%d cannot be modified",
EnumToString(type),ticket);
return(check);
}
//--- BuyLimit pending order
case ORDER_TYPE_SELL_LIMIT:
{
//--- check the distance from the opening price to the activation price
check=(newEntryPrice > Bid);
if(!check && suppressLogOutput == false)
PrintFormat("Order %s #%d cannot be modified",
EnumToString(type),ticket);
return(check);
}
break;
//--- BuyStop pending order
case ORDER_TYPE_BUY_STOP:
{
//--- check the distance from the opening price to the activation price
check=(newEntryPrice > Ask);
if(!check && suppressLogOutput == false)
PrintFormat("Order %s #%d cannot be modified",
EnumToString(type),ticket);
return(check);
}
//--- SellStop pending order
case ORDER_TYPE_SELL_STOP:
{
//--- check the distance from the opening price to the activation price
check=(newEntryPrice < Bid);
if(!check && suppressLogOutput == false)
PrintFormat("Order %s #%d cannot be modified",
EnumToString(type),ticket);
return(check);
}
break;
}
//--- order did not pass the check
return (false);
}
@@ -0,0 +1,235 @@
//+------------------------------------------------------------------+
//| CADXOnRingBuffer.mqh |
//| Copyright 2012, Konstantin Gruzdev |
//| https://login.mql5.com/ru/users/Lizar |
//| Revision 01 Dec 2012 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, Konstantin Gruzdev"
#property link "https://login.mql5.com/ru/users/Lizar"
//--- Class to calculate the MA using the ring buffer:
#include <IncOnRingBuffer\CMAOnRingBuffer.mqh>
//+------------------------------------------------------------------+
//| Class CADXOnRingBuffer |
//| Appointment: class is designed for the calculation of the |
//| ADX indicator (Average Directional Movement Index, |
//| ADX) using the class for working with the ring |
//| buffer. |
//| Link: http://www.mql5.com/ru/code/1343 |
//+------------------------------------------------------------------+
class CADXOnRingBuffer
{
public:
CMAOnRingBuffer pdi; // positive directional index
CMAOnRingBuffer ndi; // negative directional index
private:
CMAOnRingBuffer m_adx; // average directional movement index
string m_name; // indicator name
bool m_as_series; // true, if the indexing as in time series
int m_bars_required; // number of elements required to calculate
int m_begin; // index of the first significant element
int m_start; // index of element to start the calculation
int m_index; // current element index
double m_high; // maximal value
double m_low; // minimal value
double m_close; // closing price
double m_phigh; // maximum value of the previous bar
double m_plow; // minimum value of the previous bar
double m_pclose; // closing price of the previous bar
double m_PD;
double m_ND;
public:
CADXOnRingBuffer() {}
~CADXOnRingBuffer() {}
//--- initialization method:
bool Init(int ma_period=14,
ENUM_MA_METHOD ma_method=MODE_EMA,
int size_buffer=256,
bool as_series=false);
//--- basic methods:
int MainOnArray(const int rates_total,
const int prev_calculated,
const double &high[],
const double &low[],
const double &close[]);
double MainOnValue(const int rates_total,
const int prev_calculated,
const int begin,
const double high,
const double low,
const double close,
const int index);
//--- methods to get access to private data:
int BarsRequired() { return(m_bars_required); }
string NameADX() { return("ADX"+m_name); }
string NameNDI() { return("-DI"+m_name); }
string NamePDI() { return("+DI"+m_name); }
string MAMethod() { return(m_adx.MAMethod()); }
int MAPeriod() { return(m_adx.MAPeriod()); }
int Size() { return(m_adx.Size()); }
//--- returns the value of element with the specified index:
double operator [](const int index) const { return(m_adx.At(index)); }
private:
//--- indicator calculation method:
void ADX(const int rates_total, const int prev_calculated);
};
//+------------------------------------------------------------------+
//| Initialization method |
//+------------------------------------------------------------------+
bool CADXOnRingBuffer :: Init(int ma_period=14,ENUM_MA_METHOD ma_method=MODE_EMA, int size_buffer=256, bool as_series=false)
{
//--- initialize the CMAOnRingBuffer class instances:
if(!pdi.Init(ma_period,ma_method,size_buffer)) return false;
if(!ndi.Init(ma_period,ma_method,size_buffer)) return false;
if(!m_adx.Init(ma_period,ma_method,size_buffer)) return false;
//---
m_name="("+IntegerToString(ma_period)+","+MAMethod()+")";
//---
m_as_series=as_series;
m_bars_required=m_adx.BarsRequired()+1;
return true;
}
//+------------------------------------------------------------------+
//| Indicator on array |
//+------------------------------------------------------------------+
int CADXOnRingBuffer :: MainOnArray(const int rates_total,
const int prev_calculated,
const double &high[],
const double &low[],
const double &close[])
{
//--- save as_series flags:
bool as_series_high = ArrayGetAsSeries(high);
bool as_series_low = ArrayGetAsSeries(low);
bool as_series_close = ArrayGetAsSeries(close);
if(as_series_high) ArraySetAsSeries(high, false);
if(as_series_low) ArraySetAsSeries(low, false);
if(as_series_close) ArraySetAsSeries(close,false);
//--- first calculation:
if(prev_calculated==0)
{
for(int i=0;i<rates_total;i++)
{
if(high[i]!=0 && high[i] != EMPTY_VALUE &&
low[i]!=0 && low[i] != EMPTY_VALUE &&
close[i]!=0 && close[i]!= EMPTY_VALUE)
{
m_start=MathMax(i+1,rates_total-Size()-m_bars_required);
break;
}
}
m_begin=m_start;
}
//--- number of bars was changed:
else m_start=prev_calculated-1;
//--- main loop:
for(m_index=m_start;m_index<rates_total;m_index++)
{
//--- fill main positive and main negative buffers:
m_phigh = high [m_index-1];
m_plow = low [m_index-1];
m_pclose = close[m_index-1];
m_high = high [m_index];
m_low = low [m_index];
//--- calculation of the average directional movement index:
ADX(rates_total,prev_calculated);
}
//--- restore as_series flags
if(as_series_high) ArraySetAsSeries(high, true);
if(as_series_low) ArraySetAsSeries(low, true);
if(as_series_close) ArraySetAsSeries(close,true);
//--- return value of prev_calculated for next call:
return(rates_total);
}
//+------------------------------------------------------------------+
//| Indicator on value |
//+------------------------------------------------------------------+
double CADXOnRingBuffer:: MainOnValue(const int rates_total,
const int prev_calculated,
const int begin,
const double high,
const double low,
const double close,
const int index)
{
//--- check as_series flags:
if(m_as_series) m_index=rates_total-1-index;
else m_index=index;
//--- check begin:
if(m_index<begin) return(EMPTY_VALUE);
//--- initial calculation:
if(m_index==begin)
{
m_high=high;
m_low=low;
m_close=close;
m_begin=begin+1;
return(EMPTY_VALUE);
}
//--- remember the prices:
if(prev_calculated-1!=m_index)
{
m_phigh = m_high;
m_plow = m_low;
m_pclose = m_close;
}
m_high = high;
m_low = low;
m_close = close;
//--- calculation of the average directional movement index:
ADX(rates_total,prev_calculated);
//--- result:
return(m_adx.Last());
}
//+------------------------------------------------------------------+
//| Average directional movement index |
//+------------------------------------------------------------------+
void CADXOnRingBuffer:: ADX(const int rates_total, const int prev_calculated)
{
//--- fill main positive and main negative buffers
double dTmpP=m_high-m_phigh;
double dTmpN=m_plow-m_low;
if(dTmpP<0.0) dTmpP=0.0;
if(dTmpN<0.0) dTmpN=0.0;
if(dTmpP>dTmpN) dTmpN=0.0;
else
{
if(dTmpP<dTmpN) dTmpP=0.0;
else
{
dTmpP=0.0;
dTmpN=0.0;
}
}
//--- define TR
double tr=MathMax(MathMax(MathAbs(m_high-m_low),MathAbs(m_high-m_pclose)),MathAbs(m_low-m_pclose));
//---
if(tr!=0.0)
{
m_PD=100.0*dTmpP/tr;
m_ND=100.0*dTmpN/tr;
}
else
{
m_PD=0.0;
m_ND=0.0;
}
//--- main calculation:
//--- fill smoothed positive and negative buffers
pdi.MainOnValue(rates_total,prev_calculated,m_begin,m_PD,m_index);
ndi.MainOnValue(rates_total,prev_calculated,m_begin,m_ND,m_index);
//--- fill ADXTmp buffer
double dTmp=pdi.Last()+ndi.Last();
if(dTmp!=0.0)
dTmp=100.0*MathAbs((pdi.Last()-ndi.Last())/dTmp);
else
dTmp=0.0;
//--- fill smoothed ADX buffer
m_adx.MainOnValue(rates_total,prev_calculated,m_begin,dTmp,m_index);
}
+153
View File
@@ -0,0 +1,153 @@
//+------------------------------------------------------------------+
//| CArrayRing.mqh |
//| Copyright 2012, Konstantin Gruzdev |
//| https://login.mql5.com/ru/users/Lizar |
//| Revision 03 Dec 2012 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, Konstantin Gruzdev"
#property link "https://login.mql5.com/ru/users/Lizar"
//+------------------------------------------------------------------+
//| Class CArrayRing |
//| Appointment: class is designed to work with tne finite ring |
//| buffers of data. When the buffer is crowded the oldest |
//| buffer element is replaced by the newest element. Herewith, |
//| the specified number of end elements are always |
//| available. |
//| Link: http://www.mql5.com/ru/code/1340 |
//| Remark: it should also be kept in mind that the element indexing |
//| in the ring buffer is executed as in timeseries. |
//+------------------------------------------------------------------+
class CArrayRing
{
private:
double m_data[]; // ring buffer of data
int m_size; // buffer size
int m_last_pos; // last buffer element position
double m_filling; // value, which used for the array filling
public:
CArrayRing();
~CArrayRing() { ArrayFree(m_data); }
//--- buffer initialization method:
bool Init(int size, double volue=EMPTY_VALUE);
//--- method returns the buffer size:
int Size() { return m_size-1; }
//--- method changes the ring buffer size:
bool Resize(const int size);
//--- method of adding a new element to the buffer:
void Add(const double element);
//--- method returns the value of element with the specified index:
double At(const int index) const;
double operator [](const int index) const { return(At(index)); }
//--- method returns the value of the last element stored in the buffer:
double Last() const { return(m_data[m_last_pos]); }
//--- method overwrites the value of the last element in the buffer:
void Last(const double element) { m_data[m_last_pos]=element; }
//--- method overwrites the value of element with the specified index:
bool Update(const double element,const int index=0);
};
//+------------------------------------------------------------------+
//| Constructor. |
//+------------------------------------------------------------------+
CArrayRing::CArrayRing()
{
m_last_pos=0; // last element position
m_filling=EMPTY_VALUE; // value for buffer filling
m_size=ArraySize(m_data); // get size of the ring buffer
}
//+------------------------------------------------------------------+
//| Buffer initialization method. |
//+------------------------------------------------------------------+
bool CArrayRing::Init(int size, double volue=EMPTY_VALUE)
{
m_last_pos=0; // last element position
m_filling=volue; // value for buffer filling
m_size=ArraySize(m_data); // get size of the buffer
bool result=Resize(size); // create a buffer with the desired size
ArrayFill(m_data,0,m_size,m_filling); // fill the buffer with default values
return(result);
}
//+------------------------------------------------------------------+
//| Set the new size of the array. |
//+------------------------------------------------------------------+
bool CArrayRing::Resize(const int new_size)
{
//--- check
if(new_size<0) return(false);
//--- increase array size:
if(new_size>m_size)
{
int set_size=ArrayResize(m_data,new_size);
if(set_size<0) return(false);
//--- copy elements to restore their order:
if(set_size>m_size)
{
for(int i=m_size-1,j=set_size-1;i>m_last_pos;i--,j--)
{
m_data[j]=m_data[i];
m_data[i]=m_filling;
}
}
m_size=set_size;
//--- result:
return(true);
}
//--- reduce array size:
//--- prepare array to reduce the size:
if(new_size>m_last_pos+1)
for(int i=m_size-1,j=new_size-1;j>m_last_pos;i--,j--) m_data[j]=m_data[i];
else
{
for(int i=m_last_pos+1-new_size,j=0;i<=m_last_pos;i++,j++) m_data[j]=m_data[i];
m_last_pos=new_size-1;
}
//--- reduce the size:
m_size=new_size;
ArrayResize(m_data,new_size);
//--- result:
return(true);
}
//+------------------------------------------------------------------+
//| Adding a new element to the buffer. |
//+------------------------------------------------------------------+
void CArrayRing::Add(const double element)
{
m_last_pos=++m_last_pos%m_size;
m_data[m_last_pos]=element;
}
//+------------------------------------------------------------------+
//| Gets the element at the specified index. |
//+------------------------------------------------------------------+
double CArrayRing::At(const int index) const
{
//--- check the index correctness:
if((index/m_size)==0)
//--- return the value of element with the specified index:
return(m_data[(m_size+m_last_pos-index)%m_size]);
//--- if the index is wrong:
return(DBL_MAX);
}
//+------------------------------------------------------------------+
//| Update the element at the specified position in the array. |
//+------------------------------------------------------------------+
bool CArrayRing::Update(const double element,const int index=0)
{
//--- check the index correctness:
if((index/m_size)==0)
{
//--- update
m_data[(m_size+m_last_pos-index)%m_size]=element;
//--- successful
return(true);
}
//--- if the index is wrong:
return(false);
}
@@ -0,0 +1,154 @@
//+------------------------------------------------------------------+
//| CATROnRingBuffer.mqh |
//| Copyright 2012, Konstantin Gruzdev |
//| https://login.mql5.com/ru/users/Lizar |
//| Revision 01 Dec 2012 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, Konstantin Gruzdev"
#property link "https://login.mql5.com/ru/users/Lizar"
//--- Class to calculate the MA using the ring buffer:
#include <IncOnRingBuffer\CMAOnRingBuffer.mqh>
//+------------------------------------------------------------------+
//| Class CATROnRingBuffer |
//| Appointment: class is designed for the calculation of the |
//| technical indicator Average True Range (Average |
//| True Range, ATR) using the class for working with |
//| the ring buffer. |
//| Link: http://www.mql5.com/ru/code/1344 |
//+------------------------------------------------------------------+
class CATROnRingBuffer
{
private:
CMAOnRingBuffer m_ma; // instance the class for MA calculation
double m_tr; // true range
double m_atr; // average true range
string m_name; // indicator name
bool m_as_series; // true, if the indexing as in time series
int m_bars_required; // number of elements required to calculate
int m_begin; // index of the first significant element
int m_start; // index of element to start the calculation
int m_index; // current element index
double m_close; // closing price of the current bar
double m_prev_close; // closing price of the previous bar
public:
CATROnRingBuffer() {}
~CATROnRingBuffer() {}
//--- initialization method:
bool Init(int ma_period=14,ENUM_MA_METHOD ma_method=MODE_SMA, int size_buffer=256, bool as_series=false);
//--- basic methods:
int MainOnArray(const int rates_total,
const int prev_calculated,
const double &high[],
const double &low[],
const double &close[]);
double MainOnValue(const int rates_total,
const int prev_calculated,
const int begin,
const double high,
const double low,
const double close,
const int index);
//--- methods to get access to private data:
int BarsRequired() { return(m_bars_required); }
string Name() { return(m_name); }
string MAMethod() { return(m_ma.MAMethod()); }
int MAPeriod() { return(m_ma.MAPeriod()); }
int Size() { return(m_ma.Size()); }
//--- returns the value of element with the specified index:
double operator [](const int index) const { return(m_ma.At(index)); }
};
//+------------------------------------------------------------------+
//| Initialization method |
//+------------------------------------------------------------------+
bool CATROnRingBuffer :: Init(int ma_period=14,ENUM_MA_METHOD ma_method=MODE_SMA, int size_buffer=256, bool as_series=false)
{
//--- Initialization for MA:
if(!m_ma.Init(ma_period,ma_method,size_buffer)) return false;
//---
m_as_series=as_series;
m_bars_required=m_ma.BarsRequired()+1;
m_name="ATR("+IntegerToString(ma_period)+","+MAMethod()+")";
//---
return true;
}
//+------------------------------------------------------------------+
//| Indicator on array |
//+------------------------------------------------------------------+
int CATROnRingBuffer :: MainOnArray(const int rates_total,
const int prev_calculated,
const double &high[],
const double &low[],
const double &close[])
{
//--- save as_series flags:
bool as_series_high = ArrayGetAsSeries(high);
bool as_series_low = ArrayGetAsSeries(low);
bool as_series_close = ArrayGetAsSeries(close);
if(as_series_high) ArraySetAsSeries(high, false);
if(as_series_low) ArraySetAsSeries(low, false);
if(as_series_close) ArraySetAsSeries(close,false);
//--- first calculation:
if(prev_calculated==0)
{
for(int i=0;i<rates_total;i++)
{
if(high[i]!=0 && high[i]!=EMPTY_VALUE &&
low[i]!=0 && low[i]!=EMPTY_VALUE &&
close[i]!=0 && close[i]!=EMPTY_VALUE)
{
m_start=MathMax(i+1,rates_total-Size()-m_bars_required);
break;
}
}
m_begin=m_start;
}
//--- number of bars was changed:
else m_start=prev_calculated-1;
//--- main loop:
for(int i=m_start;i<rates_total;i++)
{
m_tr=MathMax(high[i],close[i-1])-MathMin(low[i],close[i-1]);
m_ma.MainOnValue(rates_total,prev_calculated,m_begin,m_tr,i);
}
//--- restore as_series flags:
if(as_series_high) ArraySetAsSeries(high, true);
if(as_series_low) ArraySetAsSeries(low, true);
if(as_series_close) ArraySetAsSeries(close,true);
//--- return value of prev_calculated for next call:
return(rates_total);
}
//+------------------------------------------------------------------+
//| Indicator on value |
//+------------------------------------------------------------------+
double CATROnRingBuffer:: MainOnValue(const int rates_total,
const int prev_calculated,
const int begin,
const double high,
const double low,
const double close,
const int index)
{
//--- check as_series flags:
if(m_as_series) m_index=rates_total-1-index;
else m_index=index;
//--- check begin:
if(m_index<begin) return(EMPTY_VALUE);
//--- initial calculation:
if(m_index==begin)
{
m_close=close;
return (EMPTY_VALUE);
}
//--- remember the closing price:
if(prev_calculated-1!=m_index) m_prev_close=close;
m_close=close;
//--- main calculation:
m_tr=MathMax(high,m_prev_close)-MathMin(low,m_prev_close);
m_ma.MainOnValue(rates_total,prev_calculated,begin+1,m_tr,m_index);
//--- result:
return(m_ma.Last());
}
+364
View File
@@ -0,0 +1,364 @@
//+------------------------------------------------------------------+
//| CMAOnRingBuffer.mqh |
//| Copyright 2012, Konstantin Gruzdev |
//| https://login.mql5.com/ru/users/Lizar |
//| Revision 30 Nov 2012 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, Konstantin Gruzdev"
#property link "https://login.mql5.com/ru/users/Lizar"
//--- Class for working with the ring buffer of data:
#include <IncOnRingBuffer\CArrayRing.mqh>
//+------------------------------------------------------------------+
//| Class CMAOnRingBuffer |
//| Appointment: class is designed to calculate a moving averages |
//| using the class for working with the ring |
//| buffer. |
//| Link: http://www.mql5.com/ru/code/1342 |
//+------------------------------------------------------------------+
class CMAOnRingBuffer :public CArrayRing
{
private:
CArrayRing *m_array_in; // ring buffer for input data
int m_ma_period; // number of elements to analyze
ENUM_MA_METHOD m_ma_method; // MA calculation method
bool m_as_series; // true, if the indexing as in time series
double m_k1,m_k2;
double m_LK[];
string m_name; // indicator name
int m_bars_required; // number of elements required to calculate
int m_start; // index of element to start the calculation
int m_index; // current element index
public:
CMAOnRingBuffer() {}
~CMAOnRingBuffer();
//--- initialization method:
bool Init(int ma_period=14,ENUM_MA_METHOD ma_method=MODE_SMA, int size_buffer=256, bool as_series=false);
//--- basic methods:
int MainOnArray(const int rates_total, const int prev_calculated,const double &array[]);
double MainOnValue(const int rates_total, const int prev_calculated, const int begin, const double value, const int index);
//--- methods to get access to private data:
int BarsRequired() { return(m_bars_required); }
string Name() { return(m_name); }
string MAMethod() { return(MethodToString(m_ma_method)); }
int MAPeriod() { return(m_ma_period); }
//--- returns the value of element with the specified index:
double operator [](const int index) const { return(At(index)); }
private:
//--- methods of calculation based on the array of input data:
void SMAOnArray (const int rates_total, const int prev_calculated, const double &array[]);
void EMAOnArray (const int rates_total, const int prev_calculated, const double &array[]);
void LWMAOnArray(const int rates_total, const int prev_calculated, const double &array[]);
//--- methods to calculate the sequential values ??of the indicator elements:
double SMAOnValue (const int prev_calculated, const int begin, const double value, const int index);
double EMAOnValue (const int prev_calculated, const int begin, const double value, const int index);
double LWMAOnValue(const int prev_calculated, const int begin, const double value, const int index);
//--- auxiliary methods:
int Begin(const int rates_total,const double &array[]);
bool FillArrayIn(const int prev_calculated, const double value);
string MethodToString(ENUM_MA_METHOD method);
};
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
void CMAOnRingBuffer:: ~CMAOnRingBuffer()
{
if(CheckPointer(m_array_in)!=POINTER_INVALID) delete m_array_in;
}
//+------------------------------------------------------------------+
//| Indicator on array |
//+------------------------------------------------------------------+
int CMAOnRingBuffer:: MainOnArray(const int rates_total,const int prev_calculated,const double &array[])
{
//--- save as_series flags
bool as_series=ArrayGetAsSeries(array);
if(as_series) ArraySetAsSeries(array,false);
//--- main calculation:
switch(m_ma_method)
{
case MODE_SMA: SMAOnArray(rates_total,prev_calculated,array); break;
case MODE_EMA:
case MODE_SMMA: EMAOnArray(rates_total,prev_calculated,array); break;
case MODE_LWMA: LWMAOnArray(rates_total,prev_calculated,array); break;
}
//--- restore as_series flags
if(as_series) ArraySetAsSeries(array,true);
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
//| Indicator on value |
//+------------------------------------------------------------------+
double CMAOnRingBuffer:: MainOnValue(const int rates_total, const int prev_calculated, const int begin, const double value, const int index)
{
//--- check as_series flags:
if(m_as_series) m_index=rates_total-1-index;
else m_index=index;
//--- check begin:
if(m_index<begin) return(EMPTY_VALUE);
//--- main calculation:
switch(m_ma_method)
{
case MODE_SMA: return(SMAOnValue(prev_calculated,begin,value,index));
case MODE_EMA:
case MODE_SMMA: return(EMAOnValue(prev_calculated,begin,value,index));
case MODE_LWMA: return(LWMAOnValue(prev_calculated,begin,value,index));
}
//--- result:
return(EMPTY_VALUE);
}
//+------------------------------------------------------------------+
//| Simple moving average on array |
//+------------------------------------------------------------------+
void CMAOnRingBuffer:: SMAOnArray(const int rates_total, const int prev_calculated, const double &array[])
{
//--- first calculation:
if(prev_calculated==0)
{
m_start=Begin(rates_total,array)+m_ma_period-1;
double sum=0.0;
for(int i=m_start;i>m_start-m_ma_period;i--) sum+=array[i];
Last(sum/m_ma_period);
}
//--- number of bars was changed:
else
{
m_start=prev_calculated-1;
Last(At(1)-(array[m_start-m_ma_period]-array[m_start])/m_ma_period);
}
//--- main loop
for(int i=m_start+1;i<rates_total && !IsStopped();i++)
Add(Last()-(array[i-m_ma_period]-array[i])/m_ma_period);
}
//+------------------------------------------------------------------+
//| Exponential moving average on array |
//+------------------------------------------------------------------+
void CMAOnRingBuffer:: EMAOnArray(const int rates_total,const int prev_calculated,const double &array[])
{
//--- first calculation:
if(prev_calculated==0)
{
m_start=Begin(rates_total,array);
Last(array[m_start]);
}
//--- number of bars was changed:
else
{
m_start=prev_calculated-1;
Last(m_k1*array[m_start]+m_k2*At(1));
}
//--- main loop:
for(int i=m_start+1;i<rates_total && !IsStopped();i++)
Add(m_k1*array[i]+m_k2*Last());
}
//+------------------------------------------------------------------+
//| Linear weighted moving average on array |
//+------------------------------------------------------------------+
void CMAOnRingBuffer:: LWMAOnArray(const int rates_total, const int prev_calculated, const double &array[])
{
//--- first calculation:
if(prev_calculated==0)
m_start=Begin(rates_total,array)+m_ma_period-1;
//--- number of bars was changed:
else m_start=prev_calculated-1;
double volue=0.0;
for(int j=0;j<m_ma_period && !IsStopped();j++)
volue+=array[m_start-j]*m_LK[j];
Last(volue);
//--- main loop
for(int i=m_start+1;i<rates_total && !IsStopped();i++)
{
volue=0.0;
for(int j=0;j<m_ma_period && !IsStopped();j++)
volue+=array[i-j]*m_LK[j];
Add(volue);
}
}
//+------------------------------------------------------------------+
//| Simple moving average on value |
//+------------------------------------------------------------------+
double CMAOnRingBuffer:: SMAOnValue(const int prev_calculated, const int begin, const double value, const int index)
{
//--- fill the ring buffer of input data:
if(!FillArrayIn(prev_calculated,value)) return(EMPTY_VALUE);
//--- initial calculation:
m_start=begin+m_ma_period-1;
if(m_index<m_start) return (EMPTY_VALUE);
else if(m_index==m_start)
{
double sum=0.0;
for(int i=0;i<m_ma_period && !IsStopped();i++) sum+=m_array_in[i];
Last(sum/m_ma_period);
return(Last());
}
//--- main calculation:
if(prev_calculated-1==m_index)
Last(At(1)-(m_array_in[m_ma_period]-value)/m_ma_period);
else
Add(Last()-(m_array_in[m_ma_period]-value)/m_ma_period);
//--- result:
return(Last());
}
//+------------------------------------------------------------------+
//| Exponential moving average on value |
//+------------------------------------------------------------------+
double CMAOnRingBuffer:: EMAOnValue(const int prev_calculated, const int begin, const double value, const int index)
{
//--- initial calculation:
if(m_index==begin)
{
Last(value);
return(value);
}
//--- main calculation:
if(prev_calculated-1==m_index)
Last(m_k1*value+m_k2*At(1));
else
Add(m_k1*value+m_k2*Last());
//--- result:
return(Last());
}
//+------------------------------------------------------------------+
//| Linear weighted moving average on value |
//+------------------------------------------------------------------+
double CMAOnRingBuffer:: LWMAOnValue(const int prev_calculated, const int begin, const double value, const int index)
{
//--- fill the ring buffer of input data:
if(!FillArrayIn(prev_calculated,value)) return(EMPTY_VALUE);
//--- initial calculation:
if(m_index<begin+m_ma_period-1) return (EMPTY_VALUE);
//--- main calculation:
double volue=0.0;
for(int j=0;j<m_ma_period && !IsStopped();j++)
volue+=m_array_in[j]*m_LK[j];
if(prev_calculated-1==m_index) Last(volue);
else Add(volue);
//--- result:
return(Last());
}
//+------------------------------------------------------------------+
//| Defines the index of the first element for calculation |
//+------------------------------------------------------------------+
int CMAOnRingBuffer:: Begin(const int rates_total,const double &array[])
{
//--- looking the start of significant data:
int i=-1;
while(++i<rates_total && !IsStopped())
{
if(array[i]!=0 && array[i]!=EMPTY_VALUE) break;
}
//--- Return the index of the element from which start calculations:
return(MathMax(i,rates_total-Size()-m_bars_required));
}
//+------------------------------------------------------------------+
//| Fill the ring buffer by input data |
//+------------------------------------------------------------------+
bool CMAOnRingBuffer:: FillArrayIn(const int prev_calculated, const double value)
{
//--- check pointer:
if(CheckPointer(m_array_in)==POINTER_INVALID)
{
if((m_array_in=new CArrayRing())==NULL) return false;
if(!m_array_in.Init(Size())) return false;
}
//--- fill the ring buffer of input data:
if(prev_calculated-1==m_index) m_array_in.Last(value);
else m_array_in.Add(value);
//--- successful
return true;
}
//+------------------------------------------------------------------+
//| Initialization method |
//+------------------------------------------------------------------+
bool CMAOnRingBuffer:: Init(int ma_period=14,ENUM_MA_METHOD ma_method=MODE_SMA, int size_buffer=256, bool as_series=false)
{
//--- check for input values
if(ma_period<=0)
{
m_ma_period=14;
printf("Input parameter ma_period has incorrect value (%d). Indicator will use value %d for calculations.",
ma_period,m_ma_period);
}
else m_ma_period=ma_period;
if(size_buffer<=m_ma_period)
{
printf("Input parameter size_buffer has incorrect value (%d). Indicator will use value %d for calculations.",
size_buffer,m_ma_period);
size_buffer=m_ma_period;
}
//--- initialization of the ring buffer for the indicator data:
if(!CArrayRing::Init(size_buffer)) return false;
//--- data initialization:
int coeff_required=10;
m_as_series=as_series;
m_ma_method=ma_method;
switch(m_ma_method)
{
case MODE_SMA:
{
m_bars_required=m_ma_period;
break;
}
case MODE_EMA:
{
m_k1=2.0/(m_ma_period+1.0);
m_k2=1.0-m_k1;
m_bars_required=m_ma_period*coeff_required;
break;
}
case MODE_SMMA:
{
m_k1=1.0/m_ma_period;
m_k2=1.0-m_k1;
m_bars_required=m_ma_period*coeff_required;
break;
}
case MODE_LWMA:
{
ArrayResize(m_LK,m_ma_period);
double sum=0;
for(int j=0;j<m_ma_period;j++) sum+=m_LK[j]=m_ma_period-j;
for(int j=0;j<m_ma_period;j++) m_LK[j]/=sum;
sum=0;
for(int j=0;j<m_ma_period;j++) sum+=m_LK[j];
m_bars_required=m_ma_period;
break;
}
default:
break;
}
m_name=MethodToString(m_ma_method)+"("+IntegerToString(m_ma_period)+")";
//--- successful
return true;
}
//+------------------------------------------------------------------+
//| Transformation of moving method in the text representation |
//+------------------------------------------------------------------+
string CMAOnRingBuffer:: MethodToString(ENUM_MA_METHOD method)
{
switch(method)
{
case MODE_SMA: return("SMA");
case MODE_EMA: return("EMA");
case MODE_LWMA: return("LWMA");
case MODE_SMMA: return("SMMA");
}
return(EnumToString(method));
}
Binary file not shown.
Binary file not shown.
+175
View File
@@ -0,0 +1,175 @@
//+------------------------------------------------------------------+
//| ma cross.mq5 |
//| Copyright 2018, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots 2
#property indicator_type1 DRAW_ARROW
#property indicator_color1 clrLightSeaGreen
#property indicator_width1 2
#property indicator_label1 "Bull ADX Cross"
#property indicator_type2 DRAW_ARROW
#property indicator_color2 clrRed
#property indicator_width2 2
#property indicator_label2 "Bear ADX Cross"
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
input int AdxPeriod = 14; // ADX period
input bool alertsOn = true; // Turn alerts on?
input bool alertsOnCurrent = false; // Alert on current bar?
input bool alertsMessage = true; // Display messages on alerts?
input bool alertsSound = false; // Play sound on alerts?
input bool alertsEmail = false; // Send email on alerts?
input bool alertsNotify = false; // Send push notification on alerts?
input int lookback = 256; // Maximum lookback period
double crossUp[],crossDn[],cross[];
#include <IncOnRingBuffer\CATROnRingBuffer.mqh>
#include <IncOnRingBuffer\CADXOnRingBuffer.mqh>
CATROnRingBuffer atr;
CADXOnRingBuffer adx;
int _start = 0;
//
// Initialize custom chart indicator for data processing
// according to settings of the custom chart indicator already on chart
//
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//
//
int OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,crossUp,INDICATOR_DATA); PlotIndexSetInteger(0,PLOT_ARROW,233);
SetIndexBuffer(1,crossDn,INDICATOR_DATA); PlotIndexSetInteger(1,PLOT_ARROW,234);
SetIndexBuffer(2,cross);
if(!adx.Init(AdxPeriod,MODE_EMA,lookback)) return(INIT_FAILED);
if(!atr.Init(15,MODE_SMA,lookback)) return(INIT_FAILED);
customChartIndicator.SetGetTimeFlag();
IndicatorSetString(INDICATOR_SHORTNAME,"ADX cross "+(string)AdxPeriod+")");
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
}
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[])
{
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,time,close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(close))
return(0);
int _prev_calculated = customChartIndicator.GetPrevCalculated();
atr.MainOnArray(rates_total,_prev_calculated,customChartIndicator.High,customChartIndicator.Low,customChartIndicator.Close);
adx.MainOnArray(rates_total,_prev_calculated,customChartIndicator.High,customChartIndicator.Low,customChartIndicator.Close);
ArraySetAsSeries(customChartIndicator.Low, false);
ArraySetAsSeries(customChartIndicator.High, false);
if(_prev_calculated==0)
{
_start = rates_total-adx.Size()+1;
}
else
_start = MathMax(_prev_calculated-1,1);
for(int i=_start;i<rates_total;i++)
{
int ix = rates_total-1-i;
cross[i] = (ix>0) ? (adx.pdi[ix]>adx.ndi[ix]) ? 1 : (adx.pdi[ix]<adx.ndi[ix]) ? 2 : cross[i-1] : 0;
crossUp[i] = EMPTY_VALUE;
crossDn[i] = EMPTY_VALUE;
if (i>0 && cross[i]!=cross[i-1])
{
if (cross[i] == 1) crossUp[i] = customChartIndicator.Low[i]-atr[ix];
if (cross[i] == 2) crossDn[i] = customChartIndicator.High[i]+atr[ix];
}
}
manageAlerts(customChartIndicator.Time,cross,rates_total);
return (rates_total);
}
//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
void manageAlerts(const datetime& _time[], double& _trend[], int bars)
{
if (alertsOn)
{
int whichBar = bars-1; if (!alertsOnCurrent) whichBar = bars-2; datetime time1 = _time[whichBar];
if (_trend[whichBar] != _trend[whichBar-1])
{
if (_trend[whichBar] == 1) doAlert(time1," plus DI crossing minus DI up");
if (_trend[whichBar] == 2) doAlert(time1," plus DI crossing minus DI down");
}
}
}
//
//
//
//
//
void doAlert(datetime forTime, string doWhat)
{
static string previousAlert="nothing";
static datetime previousTime;
if (previousAlert != doWhat || previousTime != forTime)
{
previousAlert = doWhat;
previousTime = forTime;
//
//
//
//
//
string message = TimeToString(TimeLocal(),TIME_SECONDS)+" "+_Symbol+" Adx "+doWhat;
if (alertsMessage) Alert(message);
if (alertsEmail) SendMail(_Symbol+"Adx",message);
if (alertsNotify) SendNotification(message);
if (alertsSound) PlaySound("alert2.wav");
}
}
Binary file not shown.
@@ -40,17 +40,11 @@ double ExtTmpBuffer[];
//--- global variables
int ExtADXPeriod;
//
//
//
#include <AZ-INVEST/SDK/RangeBarIndicator.mqh>
RangeBarIndicator rangeBarsIndicator;
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//
//
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
@@ -102,33 +96,36 @@ int OnCalculate(const int rates_total,
// Process data through MedianRenko indicator
//
if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,Time))
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,Time,Close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(Close))
return(0);
//
// Make the following modifications in the code below:
//
// rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated
// customChartIndicator.GetPrevCalculated() should be used instead of prev_calculated
//
// rangeBarsIndicator.Open[] should be used instead of open[]
// rangeBarsIndicator.Low[] should be used instead of low[]
// rangeBarsIndicator.High[] should be used instead of high[]
// rangeBarsIndicator.Close[] should be used instead of close[]
// customChartIndicator.Open[] should be used instead of open[]
// customChartIndicator.Low[] should be used instead of low[]
// customChartIndicator.High[] should be used instead of high[]
// customChartIndicator.Close[] should be used instead of close[]
//
// rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed
// customChartIndicator.IsNewBar (true/false) informs you if a renko brick completed
//
// rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used
// customChartIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) customChartIndicator.SetGetTimeFlag() must be called in OnInit() for customChartIndicator.Time[] to be used
//
// rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[]
// rangeBarsIndicator.Real_volume[] should be used instead of Volume[]
// (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
// customChartIndicator.Tick_volume[] should be used instead of TickVolume[]
// customChartIndicator.Real_volume[] should be used instead of Volume[]
// (!) customChartIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
//
// rangeBarsIndicator.Price[] should be used instead of Price[]
// (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used
// customChartIndicator.Price[] should be used instead of Price[]
// (!) customChartIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for customChartIndicator.Price[] to be used
//
int _prev_calculated = rangeBarsIndicator.GetPrevCalculated();
int _prev_calculated = customChartIndicator.GetPrevCalculated();
//
//
@@ -151,11 +148,11 @@ int OnCalculate(const int rates_total,
for(int i=start;i<rates_total && !IsStopped();i++)
{
//--- get some data
double Hi =rangeBarsIndicator.High[i];
double prevHi=rangeBarsIndicator.High[i-1];
double Lo =rangeBarsIndicator.Low[i];
double prevLo=rangeBarsIndicator.Low[i-1];
double prevCl=rangeBarsIndicator.Close[i-1];
double Hi =customChartIndicator.High[i];
double prevHi=customChartIndicator.High[i-1];
double Lo =customChartIndicator.Low[i];
double prevLo=customChartIndicator.Low[i-1];
double prevCl=customChartIndicator.Close[i-1];
//--- fill main positive and main negative buffers
double dTmpP=Hi-prevHi;
double dTmpN=prevLo-Lo;
Binary file not shown.
Binary file not shown.
Binary file not shown.
+143
View File
@@ -0,0 +1,143 @@
//+------------------------------------------------------------------+
//| ATR.mq5 |
//| Copyright 2009-2017, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009-2017, MetaQuotes Software Corp."
#property link "http://www.mql5.com"
#property description "Average True Range"
//--- indicator settings
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots 1
#property indicator_type1 DRAW_LINE
#property indicator_color1 DodgerBlue
#property indicator_label1 "ATR"
//--- input parameters
input int InpAtrPeriod=14; // ATR period
//--- indicator buffers
double ExtATRBuffer[];
double ExtTRBuffer[];
//--- global variable
int ExtPeriodATR;
//
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
void OnInit()
{
//--- check for input value
if(InpAtrPeriod<=0)
{
ExtPeriodATR=14;
printf("Incorrect input parameter InpAtrPeriod = %d. Indicator will use value %d for calculations.",InpAtrPeriod,ExtPeriodATR);
}
else ExtPeriodATR=InpAtrPeriod;
//--- indicator buffers mapping
SetIndexBuffer(0,ExtATRBuffer,INDICATOR_DATA);
SetIndexBuffer(1,ExtTRBuffer,INDICATOR_CALCULATIONS);
//---
IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
//--- sets first bar from what index will be drawn
PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,InpAtrPeriod);
//--- name for DataWindow and indicator subwindow label
string short_name="ATR("+string(ExtPeriodATR)+")";
IndicatorSetString(INDICATOR_SHORTNAME,short_name);
PlotIndexSetString(0,PLOT_LABEL,short_name);
//--- initialization done
}
//+------------------------------------------------------------------+
//| Average True Range |
//+------------------------------------------------------------------+
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[])
{
//
// Process data through MedianRenko indicator
//
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,time,close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(close))
return(0);
//
// Make the following modifications in the code below:
//
// customChartIndicator.GetPrevCalculated() should be used instead of prev_calculated
//
// customChartIndicator.Open[] should be used instead of open[]
// customChartIndicator.Low[] should be used instead of low[]
// customChartIndicator.High[] should be used instead of high[]
// customChartIndicator.Close[] should be used instead of close[]
//
// customChartIndicator.IsNewBar (true/false) informs you if a renko brick completed
//
// customChartIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) customChartIndicator.SetGetTimeFlag() must be called in OnInit() for customChartIndicator.Time[] to be used
//
// customChartIndicator.Tick_volume[] should be used instead of TickVolume[]
// customChartIndicator.Real_volume[] should be used instead of Volume[]
// (!) customChartIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
//
// customChartIndicator.Price[] should be used instead of Price[]
// (!) customChartIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for customChartIndicator.Price[] to be used
//
int _prev_calculated = customChartIndicator.GetPrevCalculated();
//
//
//
int i,limit;
//--- check for bars count
if(rates_total<=ExtPeriodATR)
return(0); // not enough bars for calculation
//--- preliminary calculations
if(_prev_calculated==0)
{
ExtTRBuffer[0]=0.0;
ExtATRBuffer[0]=0.0;
//--- filling out the array of True Range values for each period
for(i=1;i<rates_total && !IsStopped();i++)
ExtTRBuffer[i]=MathMax(customChartIndicator.High[i],customChartIndicator.Close[i-1])-MathMin(customChartIndicator.Low[i],customChartIndicator.Close[i-1]);
//--- first AtrPeriod values of the indicator are not calculated
double firstValue=0.0;
for(i=1;i<=ExtPeriodATR;i++)
{
ExtATRBuffer[i]=0.0;
firstValue+=ExtTRBuffer[i];
}
//--- calculating the first value of the indicator
firstValue/=ExtPeriodATR;
ExtATRBuffer[ExtPeriodATR]=firstValue;
limit=ExtPeriodATR+1;
}
else limit=_prev_calculated-1;
//--- the main loop of calculations
for(i=limit;i<rates_total && !IsStopped();i++)
{
ExtTRBuffer[i]=MathMax(customChartIndicator.High[i],customChartIndicator.Close[i-1])-MathMin(customChartIndicator.Low[i],customChartIndicator.Close[i-1]);
ExtATRBuffer[i]=ExtATRBuffer[i-1]+(ExtTRBuffer[i]-ExtTRBuffer[i-ExtPeriodATR])/ExtPeriodATR;
}
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
Binary file not shown.
Binary file not shown.
@@ -19,18 +19,14 @@ double ExtAOBuffer[];
double ExtColorBuffer[];
double ExtFastBuffer[];
double ExtSlowBuffer[];
//--- handles for MAs
int ExtFastSMAHandle;
int ExtSlowSMAHandle;
//--- bars minimum for calculation
#define DATA_LIMIT 33
//
//
#include <AZ-INVEST/SDK/RangeBarIndicator.mqh>
RangeBarIndicator rangeBarsIndicator;
#include <MovingAverages.mqh>
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//
@@ -54,11 +50,8 @@ void OnInit()
//--- get handles
//ExtFastSMAHandle=iMA(NULL,0,5,0,MODE_SMA,PRICE_MEDIAN);
//ExtSlowSMAHandle=iMA(NULL,0,34,0,MODE_SMA,PRICE_MEDIAN);
// renko mod
// ExtFastSMAHandle=iCustom(Symbol(),_Period,"RangeBars\\Indicators\\RangeBars_MA",5,0,MODE_SMA,PRICE_MEDIAN,true);
// ExtSlowSMAHandle=iCustom(Symbol(),_Period,"RangeBars\\Indicators\\RangeBars_MA",34,0,MODE_SMA,PRICE_MEDIAN,true);
ExtFastSMAHandle=iCustom(Symbol(),_Period,"RangeBars\\RangeBars_MA",5,0,MODE_SMA,PRICE_MEDIAN,true);
ExtSlowSMAHandle=iCustom(Symbol(),_Period,"RangeBars\\RangeBars_MA",34,0,MODE_SMA,PRICE_MEDIAN,true);
// -- Set applied price to MEDIAN as required by AO indicator
customChartIndicator.SetUseAppliedPriceFlag(PRICE_MEDIAN);
//---- initialization done
}
//+------------------------------------------------------------------+
@@ -80,48 +73,21 @@ int OnCalculate(const int rates_total,
if(rates_total<=DATA_LIMIT)
return(0);// not enough bars for calculation
//--- not all data may be calculated
int calculated=BarsCalculated(ExtFastSMAHandle);
if(calculated<rates_total)
{
Print("Not all data of ExtFastSMAHandle is calculated (",calculated,"bars ). Error",GetLastError());
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,time,close))
return(0);
}
calculated=BarsCalculated(ExtSlowSMAHandle);
if(calculated<rates_total)
{
Print("Not all data of ExtSlowSMAHandle is calculated (",calculated,"bars ). Error",GetLastError());
return(0);
}
//--- renko mod
if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,time))
if(!customChartIndicator.BufferSynchronizationCheck(close))
return(0);
int _prev_calculated = rangeBarsIndicator.GetPrevCalculated();
int _prev_calculated = customChartIndicator.GetPrevCalculated();
//--- we can copy not all data
int to_copy;
if(_prev_calculated>rates_total || _prev_calculated<0) to_copy=rates_total;
else
{
to_copy=rates_total-prev_calculated;
if(_prev_calculated>0) to_copy++;
}
//--- get FastSMA buffer
//--- get Fast MA buffer
if(IsStopped()) return(0); //Checking for stop flag
SimpleMAOnBuffer(rates_total,_prev_calculated,0,5,customChartIndicator.Price,ExtFastBuffer);
//--- get Slow MA buffer
if(IsStopped()) return(0); //Checking for stop flag
if(CopyBuffer(ExtFastSMAHandle,0,0,to_copy,ExtFastBuffer)<=0)
{
Print("Getting fast SMA is failed! Error",GetLastError());
return(0);
}
//--- get SlowSMA buffer
if(IsStopped()) return(0); //Checking for stop flag
if(CopyBuffer(ExtSlowSMAHandle,0,0,to_copy,ExtSlowBuffer)<=0)
{
Print("Getting slow SMA is failed! Error",GetLastError());
return(0);
}
SimpleMAOnBuffer(rates_total,_prev_calculated,0,35,customChartIndicator.Price,ExtSlowBuffer);
//--- first calculation or number of bars was changed
int i,limit;
if(_prev_calculated<=DATA_LIMIT)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+83
View File
@@ -0,0 +1,83 @@
//+------------------------------------------------------------------
#property copyright "mladen"
#property link "mladenfx@gmail.com"
#property link "https://www.mql5.com"
#property description "CCI (alternative)"
//+------------------------------------------------------------------
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots 1
#property indicator_label1 "CCI alternative"
#property indicator_type1 DRAW_COLOR_LINE
#property indicator_color1 clrDarkGray,clrSkyBlue,clrDodgerBlue
#property indicator_width1 2
//--- input parameters
input int inpPeriod=14; // CCI period
//--- buffers and global variables declarations
double val[],valc[],prices[];
//
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,val,INDICATOR_DATA);
SetIndexBuffer(1,valc,INDICATOR_COLOR_INDEX);
SetIndexBuffer(2,prices,INDICATOR_CALCULATIONS);
//---
IndicatorSetString(INDICATOR_SHORTNAME,"CCI (alternative)("+(string)inpPeriod+")");
return (INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator de-initialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
}
//+------------------------------------------------------------------+
//| 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[])
{
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,time,close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(close))
return(0);
int _prev_calculated = customChartIndicator.GetPrevCalculated();
///
if(Bars(_Symbol,_Period)<rates_total) return(_prev_calculated);
int i=(int)MathMax(_prev_calculated-1,1); for(; i<rates_total && !_StopFlag; i++)
{
int _start=MathMax(i-inpPeriod+1,0);
prices[i]=(customChartIndicator.High[ArrayMaximum(customChartIndicator.High,_start,inpPeriod)]+customChartIndicator.Low[ArrayMinimum(customChartIndicator.Low,_start,inpPeriod)]+customChartIndicator.Close[i])/3;
double avg = 0; for(int k=0; k<inpPeriod && (i-k)>=0; k++) avg += prices[i-k]; avg /= inpPeriod;
double dev = 0; for(int k=0; k<inpPeriod && (i-k)>=0; k++) dev += MathAbs(prices[i-k]-avg); dev /= inpPeriod;
val[i] = (dev!=0) ? (prices[i]-avg)/(0.015*dev) : 0;
valc[i]=(i>0) ?(val[i]>val[i-1]) ? 1 :(val[i]<val[i-1]) ? 2 : valc[i-1]: 0;
}
return (i);
}
//+------------------------------------------------------------------+
Binary file not shown.
@@ -29,15 +29,10 @@ double ExtDBuffer[];
double ExtMBuffer[];
double ExtCCIBuffer[];
//
//
//
#include <AZ-INVEST/SDK/RangeBarIndicator.mqh>
RangeBarIndicator rangeBarsIndicator;
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//
//
//+------------------------------------------------------------------+
@@ -50,7 +45,7 @@ void OnInit()
// Indicator uses Price[] array for calculations so we need to set this in the MedianRenkoIndicator class
//
rangeBarsIndicator.SetUseAppliedPriceFlag(InpApplyToPrice);
customChartIndicator.SetUseAppliedPriceFlag(InpApplyToPrice);
//
//
@@ -100,33 +95,36 @@ int OnCalculate(const int rates_total,const int prev_calculated,
// Process data through MedianRenko indicator
//
if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,Time))
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,Time,Close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(Close))
return(0);
//
// Make the following modifications in the code below:
//
// rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated
// customChartIndicator.GetPrevCalculated() should be used instead of prev_calculated
//
// rangeBarsIndicator.Open[] should be used instead of open[]
// rangeBarsIndicator.Low[] should be used instead of low[]
// rangeBarsIndicator.High[] should be used instead of high[]
// rangeBarsIndicator.Close[] should be used instead of close[]
// customChartIndicator.Open[] should be used instead of open[]
// customChartIndicator.Low[] should be used instead of low[]
// customChartIndicator.High[] should be used instead of high[]
// customChartIndicator.Close[] should be used instead of close[]
//
// rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed
// customChartIndicator.IsNewBar (true/false) informs you if a renko brick completed
//
// rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used
// customChartIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) customChartIndicator.SetGetTimeFlag() must be called in OnInit() for customChartIndicator.Time[] to be used
//
// rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[]
// rangeBarsIndicator.Real_volume[] should be used instead of Volume[]
// (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
// customChartIndicator.Tick_volume[] should be used instead of TickVolume[]
// customChartIndicator.Real_volume[] should be used instead of Volume[]
// (!) customChartIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
//
// rangeBarsIndicator.Price[] should be used instead of Price[]
// (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used
// customChartIndicator.Price[] should be used instead of Price[]
// (!) customChartIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for customChartIndicator.Price[] to be used
//
int _prev_calculated = rangeBarsIndicator.GetPrevCalculated();
int _prev_calculated = customChartIndicator.GetPrevCalculated();
//
//
@@ -150,13 +148,13 @@ int OnCalculate(const int rates_total,const int prev_calculated,
for(i=pos;i<rates_total && !IsStopped();i++)
{
//--- SMA on price buffer
ExtSPBuffer[i]=SimpleMA(i,ExtCCIPeriod,rangeBarsIndicator.Price);
ExtSPBuffer[i]=SimpleMA(i,ExtCCIPeriod,customChartIndicator.Price);
//--- calculate D
dTmp=0.0;
for(j=0;j<ExtCCIPeriod;j++) dTmp+=MathAbs(rangeBarsIndicator.Price[i-j]-ExtSPBuffer[i]);
for(j=0;j<ExtCCIPeriod;j++) dTmp+=MathAbs(customChartIndicator.Price[i-j]-ExtSPBuffer[i]);
ExtDBuffer[i]=dTmp*dMul;
//--- calculate M
ExtMBuffer[i]=rangeBarsIndicator.Price[i]-ExtSPBuffer[i];
ExtMBuffer[i]=customChartIndicator.Price[i]-ExtSPBuffer[i];
//--- calculate CCI
if(ExtDBuffer[i]!=0.0) ExtCCIBuffer[i]=ExtMBuffer[i]/ExtDBuffer[i];
else ExtCCIBuffer[i]=0.0;
Binary file not shown.
+145
View File
@@ -0,0 +1,145 @@
//+------------------------------------------------------------------+
//| CHV.mq5 |
//| Copyright 2009-2017, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009-2017, MetaQuotes Software Corp."
#property link "http://www.mql5.com"
#property description "Chaikin Volatility"
#include <MovingAverages.mqh>
//--- indicator settings
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots 1
#property indicator_type1 DRAW_LINE
#property indicator_color1 DodgerBlue
//--- enum
enum SmoothMethod
{
SMA=0,// Simple MA
EMA=1 // Exponential MA
};
//--- input parameters
input int InpSmoothPeriod=10; // Smoothing period
input int InpCHVPeriod=10; // CHV period
input SmoothMethod InpSmoothType=EMA; // Smoothing method
//---- buffers
double ExtCHVBuffer[];
double ExtHLBuffer[];
double ExtSHLBuffer[];
//--- global variables
int ExtSmoothPeriod,ExtCHVPeriod;
//
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
void OnInit()
{
//--- check for input variables
string MAName;
//--- set MA name
if(InpSmoothType==SMA)
MAName="SMA";
else
MAName="EMA";
//--- check inputs
if(InpSmoothPeriod<=0)
{
ExtSmoothPeriod=10;
printf("Incorrect value for input variable InpSmoothPeriod=%d. Indicator will use value=%d for calculations.",InpSmoothPeriod,ExtSmoothPeriod);
}
else ExtSmoothPeriod=InpSmoothPeriod;
if(InpCHVPeriod<=0)
{
ExtCHVPeriod=10;
printf("Incorrect value for input variable InpCHVPeriod=%d. Indicator will use value=%d for calculations.",InpCHVPeriod,ExtCHVPeriod);
}
else ExtCHVPeriod=InpCHVPeriod;
//---- define buffers
SetIndexBuffer(0,ExtCHVBuffer);
SetIndexBuffer(1,ExtHLBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(2,ExtSHLBuffer,INDICATOR_CALCULATIONS);
//--- set draw begin
PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ExtSmoothPeriod+ExtCHVPeriod-1);
//--- set index label
PlotIndexSetString(0,PLOT_LABEL,"CHV("+string(ExtSmoothPeriod)+","+MAName+")");
//--- indicator name
IndicatorSetString(INDICATOR_SHORTNAME,"Chaikin Volatility("+string(ExtSmoothPeriod)+","+MAName+")");
//--- round settings
IndicatorSetInteger(INDICATOR_DIGITS,1);
//---- OnInit done
}
//+------------------------------------------------------------------+
//| 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[])
{
//--- variables of indicator
int i,pos,posCHV;
//--- check for rates total
posCHV=ExtCHVPeriod+ExtSmoothPeriod-2;
if(rates_total<posCHV)
return(0);
//
// Process data through MedianRenko indicator
//
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,time,close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(close))
return(0);
int _prev_calculated = customChartIndicator.GetPrevCalculated();
//
//
//
//--- start working
if(_prev_calculated<1)
pos=0;
else pos=_prev_calculated-1;
//--- fill H-L(i) buffer
for(i=pos;i<rates_total && !IsStopped();i++) ExtHLBuffer[i]=customChartIndicator.High[i]-customChartIndicator.Low[i];
//--- calculate smoothed H-L(i) buffer
if(pos<ExtSmoothPeriod-1)
{
pos=ExtSmoothPeriod-1;
for(i=0;i<pos;i++) ExtSHLBuffer[i]=0.0;
}
if(InpSmoothType==SMA)
SimpleMAOnBuffer(rates_total,_prev_calculated,0,ExtSmoothPeriod,ExtHLBuffer,ExtSHLBuffer);
else
ExponentialMAOnBuffer(rates_total,_prev_calculated,0,ExtSmoothPeriod,ExtHLBuffer,ExtSHLBuffer);
//--- correct calc position
if(pos<posCHV) pos=posCHV;
//--- calculate CHV buffer
for(i=pos;i<rates_total && !IsStopped();i++)
{
if(ExtSHLBuffer[i-ExtCHVPeriod]!=0.0)
ExtCHVBuffer[i]=100.0*(ExtSHLBuffer[i]-ExtSHLBuffer[i-ExtCHVPeriod])/ExtSHLBuffer[i-ExtCHVPeriod];
else
ExtCHVBuffer[i]=0.0;
}
//----
return(rates_total);
}
//+------------------------------------------------------------------+
Binary file not shown.
Binary file not shown.
@@ -55,15 +55,10 @@ double dtoss[];
double dtosf1[];
double dtosf2[];
//
//
//
#include <AZ-INVEST/SDK/RangeBarIndicator.mqh>
RangeBarIndicator rangeBarsIndicator;
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//
//
//+------------------------------------------------------------------+
@@ -110,33 +105,36 @@ int OnCalculate(const int rates_total,const int prev_calculated,
// Process data through MedianRenko indicator
//
if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,Time))
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,Time,Close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(Close))
return(0);
//
// Make the following modifications in the code below:
//
// rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated
// customChartIndicator.GetPrevCalculated() should be used instead of prev_calculated
//
// rangeBarsIndicator.Open[] should be used instead of open[]
// rangeBarsIndicator.Low[] should be used instead of low[]
// rangeBarsIndicator.High[] should be used instead of high[]
// rangeBarsIndicator.Close[] should be used instead of close[]
// customChartIndicator.Open[] should be used instead of open[]
// customChartIndicator.Low[] should be used instead of low[]
// customChartIndicator.High[] should be used instead of high[]
// customChartIndicator.Close[] should be used instead of close[]
//
// rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed
// customChartIndicator.IsNewBar (true/false) informs you if a renko brick completed
//
// rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used
// customChartIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) customChartIndicator.SetGetTimeFlag() must be called in OnInit() for customChartIndicator.Time[] to be used
//
// rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[]
// rangeBarsIndicator.Real_volume[] should be used instead of Volume[]
// (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
// customChartIndicator.Tick_volume[] should be used instead of TickVolume[]
// customChartIndicator.Real_volume[] should be used instead of Volume[]
// (!) customChartIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
//
// rangeBarsIndicator.Price[] should be used instead of Price[]
// (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used
// customChartIndicator.Price[] should be used instead of Price[]
// (!) customChartIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for customChartIndicator.Price[] to be used
//
int _prev_calculated = rangeBarsIndicator.GetPrevCalculated();
int _prev_calculated = customChartIndicator.GetPrevCalculated();
//
//
@@ -155,7 +153,7 @@ int OnCalculate(const int rates_total,const int prev_calculated,
for (int i=(int)MathMax(_prev_calculated-1,0); i<rates_total; i++)
{
rsibuf[i] = iRsi(rangeBarsIndicator.Close[i],RsiPeriod,i,rates_total);
rsibuf[i] = iRsi(customChartIndicator.Close[i],RsiPeriod,i,rates_total);
double min = rsibuf[i];
double max = rsibuf[i];
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+133
View File
@@ -0,0 +1,133 @@
//+------------------------------------------------------------------+
//| Envelopes.mq5 |
//| Copyright 2009, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link "http://www.mql5.com"
//--- indicator settings
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots 2
#property indicator_type1 DRAW_LINE
#property indicator_type2 DRAW_LINE
#property indicator_color1 Blue
#property indicator_color2 Red
#property indicator_label1 "Upper band"
#property indicator_label2 "Lower band"
//--- input parameters
input int InpMAPeriod=14; // Period
input int InpMAShift=0; // Shift
input ENUM_MA_METHOD InpMAMethod=MODE_SMA; // Method
input ENUM_APPLIED_PRICE InpAppliedPrice=PRICE_CLOSE; // Applied price
input double InpDeviation=0.1; // Deviation
//--- indicator buffers
double ExtUpBuffer[];
double ExtDownBuffer[];
double ExtMABuffer[];
int weightSum;
//--- MA handle
//int ExtMAHandle;
#include <MovingAverages.mqh>
#include <AZ-INVEST/CustomBarConfig.mqh>
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
void OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,ExtUpBuffer,INDICATOR_DATA);
SetIndexBuffer(1,ExtDownBuffer,INDICATOR_DATA);
SetIndexBuffer(2,ExtMABuffer,INDICATOR_CALCULATIONS);
//---
IndicatorSetInteger(INDICATOR_DIGITS,_Digits+1);
//--- sets first bar from what index will be drawn
PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,InpMAPeriod-1);
//--- name for DataWindow
IndicatorSetString(INDICATOR_SHORTNAME,"Env("+string(InpMAPeriod)+")");
PlotIndexSetString(0,PLOT_LABEL,"Env("+string(InpMAPeriod)+")Upper");
PlotIndexSetString(1,PLOT_LABEL,"Env("+string(InpMAPeriod)+")Lower");
//---- line shifts when drawing
PlotIndexSetInteger(0,PLOT_SHIFT,InpMAShift);
PlotIndexSetInteger(1,PLOT_SHIFT,InpMAShift);
//---
customChartIndicator.SetUseAppliedPriceFlag(InpAppliedPrice);
//--- initialization done
}
//+------------------------------------------------------------------+
//| Envelopes |
//+------------------------------------------------------------------+
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 &TickVolume[],
const long &Volume[],
const int &Spread[])
{
int i,limit;
//--- check for bars count
if(rates_total<InpMAPeriod)
return(0);
//--
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,Time,Close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(Close))
return(0);
int _prev_calculated = customChartIndicator.GetPrevCalculated();
//--- we can copy not all data
int to_copy;
if(_prev_calculated>rates_total || _prev_calculated<0) to_copy=rates_total;
else
{
to_copy=rates_total-_prev_calculated;
if(_prev_calculated>0) to_copy++;
}
//---- get ma buffer
if(IsStopped()) return(0); //Checking for stop flag
switch(InpMAMethod)
{
case MODE_SMA:
SimpleMAOnBuffer(rates_total,_prev_calculated,0,InpMAPeriod,customChartIndicator.Price,ExtMABuffer);
break;
case MODE_EMA:
ExponentialMAOnBuffer(rates_total,_prev_calculated,0,InpMAPeriod,customChartIndicator.Price,ExtMABuffer);
break;
case MODE_SMMA:
SmoothedMAOnBuffer(rates_total,_prev_calculated,0,InpMAPeriod,customChartIndicator.Price,ExtMABuffer);
break;
case MODE_LWMA:
LinearWeightedMAOnBuffer(rates_total,_prev_calculated,0,InpMAPeriod,customChartIndicator.Price,ExtMABuffer,weightSum);
break;
}
//--- preliminary calculations
limit=_prev_calculated-1;
if(limit<InpMAPeriod)
limit=InpMAPeriod;
//--- the main loop of calculations
for(i=limit;i<rates_total && !IsStopped();i++)
{
ExtUpBuffer[i]=(1+InpDeviation/100.0)*ExtMABuffer[i];
ExtDownBuffer[i]=(1-InpDeviation/100.0)*ExtMABuffer[i];
}
//--- done
return(rates_total);
}
//+------------------------------------------------------------------+
Binary file not shown.
@@ -21,15 +21,10 @@ double ExtLowerBuffer[];
//--- 10 pixels upper from high price
int ExtArrowShift=-10;
//
//
//
#include <AZ-INVEST/SDK/RangeBarIndicator.mqh>
RangeBarIndicator rangeBarsIndicator;
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//
//
//+------------------------------------------------------------------+
@@ -69,33 +64,36 @@ int OnCalculate(const int rates_total,const int prev_calculated,
// Process data through MedianRenko indicator
//
if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,Time))
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,Time,Close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(Close))
return(0);
//
// Make the following modifications in the code below:
//
// rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated
// customChartIndicator.GetPrevCalculated() should be used instead of prev_calculated
//
// rangeBarsIndicator.Open[] should be used instead of open[]
// rangeBarsIndicator.Low[] should be used instead of low[]
// rangeBarsIndicator.High[] should be used instead of high[]
// rangeBarsIndicator.Close[] should be used instead of close[]
// customChartIndicator.Open[] should be used instead of open[]
// customChartIndicator.Low[] should be used instead of low[]
// customChartIndicator.High[] should be used instead of high[]
// customChartIndicator.Close[] should be used instead of close[]
//
// rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed
// customChartIndicator.IsNewBar (true/false) informs you if a renko brick completed
//
// rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used
// customChartIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) customChartIndicator.SetGetTimeFlag() must be called in OnInit() for customChartIndicator.Time[] to be used
//
// rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[]
// rangeBarsIndicator.Real_volume[] should be used instead of Volume[]
// (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
// customChartIndicator.Tick_volume[] should be used instead of TickVolume[]
// customChartIndicator.Real_volume[] should be used instead of Volume[]
// (!) customChartIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
//
// rangeBarsIndicator.Price[] should be used instead of Price[]
// (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used
// customChartIndicator.Price[] should be used instead of Price[]
// (!) customChartIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for customChartIndicator.Price[] to be used
//
int _prev_calculated = rangeBarsIndicator.GetPrevCalculated();
int _prev_calculated = customChartIndicator.GetPrevCalculated();
//
//
@@ -118,13 +116,13 @@ int OnCalculate(const int rates_total,const int prev_calculated,
for(i=limit; i<rates_total-3 && !IsStopped();i++)
{
//---- Upper Fractal
if(rangeBarsIndicator.High[i]>rangeBarsIndicator.High[i+1] && rangeBarsIndicator.High[i]>rangeBarsIndicator.High[i+2] && rangeBarsIndicator.High[i]>=rangeBarsIndicator.High[i-1] && rangeBarsIndicator.High[i]>=rangeBarsIndicator.High[i-2])
ExtUpperBuffer[i]=rangeBarsIndicator.High[i];
if(customChartIndicator.High[i]>customChartIndicator.High[i+1] && customChartIndicator.High[i]>customChartIndicator.High[i+2] && customChartIndicator.High[i]>=customChartIndicator.High[i-1] && customChartIndicator.High[i]>=customChartIndicator.High[i-2])
ExtUpperBuffer[i]=customChartIndicator.High[i];
else ExtUpperBuffer[i]=EMPTY_VALUE;
//---- Lower Fractal
if(rangeBarsIndicator.Low[i]<rangeBarsIndicator.Low[i+1] && rangeBarsIndicator.Low[i]<rangeBarsIndicator.Low[i+2] && rangeBarsIndicator.Low[i]<=rangeBarsIndicator.Low[i-1] && rangeBarsIndicator.Low[i]<=rangeBarsIndicator.Low[i-2])
ExtLowerBuffer[i]=rangeBarsIndicator.Low[i];
if(customChartIndicator.Low[i]<customChartIndicator.Low[i+1] && customChartIndicator.Low[i]<customChartIndicator.Low[i+2] && customChartIndicator.Low[i]<=customChartIndicator.Low[i-1] && customChartIndicator.Low[i]<=customChartIndicator.Low[i-2])
ExtLowerBuffer[i]=customChartIndicator.Low[i];
else ExtLowerBuffer[i]=EMPTY_VALUE;
}
//--- OnCalculate done. Return new prev_calculated.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,401 @@
//------------------------------------------------------------------
#property copyright "mladen"
#property link "www.forex-tsd.com"
//------------------------------------------------------------------
#property indicator_chart_window
#property indicator_buffers 6
#property indicator_plots 3
#property indicator_label1 "Gann zone"
#property indicator_type1 DRAW_FILLING
#property indicator_color1 clrGainsboro,clrGainsboro
#property indicator_label2 "Gann middle"
#property indicator_type2 DRAW_LINE
#property indicator_style2 STYLE_DOT
#property indicator_color2 clrGray
#property indicator_label3 "Gann high/low"
#property indicator_type3 DRAW_COLOR_LINE
#property indicator_color3 clrDimGray,clrLimeGreen,clrDarkOrange
#property indicator_width3 2
//
//
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//
enum enMaTypes
{
ma_sma, // Simple moving average
ma_ema, // Exponential moving average
ma_smma, // Smoothed MA
ma_lwma // Linear weighted MA
};
enum enFilterWhat
{
flt_prc, // Filter the prices
flt_val, // Filter the averages value
flt_all // Filter all
};
ENUM_TIMEFRAMES TimeFrame = PERIOD_CURRENT; // Time frame
input int AvgPeriod = 10; // Average period
input enMaTypes AvgType = ma_sma; // Average method
input double Filter = 0; // Filter to use (<=0 for no filter)
input enFilterWhat FilterOn = flt_prc; // Filter :
input bool alertsOn = false; // Turn alerts on?
input bool alertsOnCurrent = true; // Alert on current bar?
input bool alertsMessage = true; // Display messageas on alerts?
input bool alertsSound = false; // Play sound on alerts?
input bool alertsEmail = false; // Send email on alerts?
input bool alertsNotify = false; // Send push notification on alerts?
input bool Interpolate = true; // Interpolate mtf data ?
double sup[],supc[],mid[],fup[],fdn[],_count[];
ENUM_TIMEFRAMES timeFrame;
string indName;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
int OnInit()
{
SetIndexBuffer(0,fup,INDICATOR_DATA);
SetIndexBuffer(1,fdn,INDICATOR_DATA);
SetIndexBuffer(2,mid,INDICATOR_DATA);
SetIndexBuffer(3,sup,INDICATOR_DATA);
SetIndexBuffer(4,supc,INDICATOR_COLOR_INDEX);
SetIndexBuffer(5,_count,INDICATOR_CALCULATIONS);
//
//
//
//
//
customChartIndicator.SetGetTimeFlag();
// timeFrame = MathMax(_Period,TimeFrame);
indName = getIndicatorName();
IndicatorSetString(INDICATOR_SHORTNAME,periodToString(timeFrame)+" Gann high/low activator("+string(AvgPeriod)+")");
return(0);
}
//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
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[])
{
if (Bars(_Symbol,_Period)<rates_total) return(-1);
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,time,close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(close))
return(0);
int _prev_calculated = customChartIndicator.GetPrevCalculated();
double pfilter = Filter; if (FilterOn==flt_val) pfilter=0;
double vfilter = Filter; if (FilterOn==flt_prc) vfilter=0;
for (int i=(int)MathMax(_prev_calculated-1,1); i<rates_total && !IsStopped(); i++)
{
fup[i] = iFilter(iCustomMa(AvgType,iFilter(customChartIndicator.High[i-1],pfilter,AvgPeriod,i,rates_total,0),AvgPeriod,i,rates_total,0),vfilter,AvgPeriod,i,rates_total,1);
fdn[i] = iFilter(iCustomMa(AvgType,iFilter(customChartIndicator.Low[i-1] ,pfilter,AvgPeriod,i,rates_total,2),AvgPeriod,i,rates_total,1),vfilter,AvgPeriod,i,rates_total,3);
mid[i] = (fup[i]+fdn[i])/2.0;
double pclose = iFilter(customChartIndicator.Close[i],pfilter,AvgPeriod,i,rates_total,4);
supc[i] = (pclose>fup[i]) ? 1 : (pclose<fdn[i]) ? 2 : supc[i-1];
sup[i] = (supc[i]==1) ? fdn[i] : (supc[i]==2) ? fup[i] : pclose;
}
manageAlerts(customChartIndicator.Time,supc,rates_total);
_count[rates_total-1] = MathMax(rates_total-_prev_calculated+1,1);
return(rates_total);
}
//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
#define _filterInstances 5
double workFil[][_filterInstances*3];
#define _fchange 0
#define _fachang 1
#define _fvalue 2
double iFilter(double value, double filter, int period, int i, int bars, int instanceNo=0)
{
if (filter<=0 || period<=0) return(value);
if (ArrayRange(workFil,0)!= bars) ArrayResize(workFil,bars); instanceNo*=3;
//
//
//
//
//
workFil[i][instanceNo+_fvalue] = value;
if (i>0)
{
workFil[i][instanceNo+_fchange] = MathAbs(workFil[i][instanceNo+_fvalue]-workFil[i-1][instanceNo+_fvalue]);
workFil[i][instanceNo+_fachang] = workFil[i][instanceNo+_fchange];
double fdev=0, fdif=0;
for (int k=1; k<period && (i-k)>=0; k++) workFil[i][instanceNo+_fachang] += workFil[i-k][instanceNo+_fchange]; workFil[i][instanceNo+_fachang] /= (double)period;
for (int k=0; k<period && (i-k)>=0; k++) fdev += MathPow(workFil[i-k][instanceNo+_fchange]-workFil[i-k][instanceNo+_fachang],2); fdev = MathSqrt(fdev/(double)period); fdif = filter*fdev;
if (MathAbs(workFil[i][instanceNo+_fvalue]-workFil[i-1][instanceNo+_fvalue])<fdif)
workFil[i][instanceNo+_fvalue]=workFil[i-1][instanceNo+_fvalue];
}
return(workFil[i][instanceNo+_fvalue]);
}
//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
void manageAlerts(const datetime& time[], double& trend[], int bars)
{
if (!alertsOn) return;
int whichBar = bars-1; if (!alertsOnCurrent) whichBar = bars-2; datetime time1 = time[whichBar];
if (trend[whichBar] != trend[whichBar-1])
{
if (trend[whichBar] == 1) doAlert(time1,"up");
if (trend[whichBar] == 2) doAlert(time1,"down");
}
}
//
//
//
//
//
void doAlert(datetime forTime, string doWhat)
{
static string previousAlert="nothing";
static datetime previousTime;
string message;
if (previousAlert != doWhat || previousTime != forTime)
{
previousAlert = doWhat;
previousTime = forTime;
//
//
//
//
//
message = periodToString(_Period)+" "+_Symbol+" at "+TimeToString(TimeLocal(),TIME_SECONDS)+" Gann high/low activator state changed to "+doWhat;
if (alertsMessage) Alert(message);
if (alertsEmail) SendMail(_Symbol+" Gann high/low activator",message);
if (alertsNotify) SendNotification(message);
if (alertsSound) PlaySound("alert2.wav");
}
}
//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
#define _maInstances 2
#define _maWorkBufferx1 1*_maInstances
#define _maWorkBufferx2 2*_maInstances
double iCustomMa(int mode, double price, double length, int r, int bars, int instanceNo=0)
{
switch (mode)
{
case ma_sma : return(iSma(price,(int)length,r,bars,instanceNo));
case ma_ema : return(iEma(price,length,r,bars,instanceNo));
case ma_smma : return(iSmma(price,(int)length,r,bars,instanceNo));
case ma_lwma : return(iLwma(price,(int)length,r,bars,instanceNo));
default : return(price);
}
}
//
//
//
//
//
double workSma[][_maWorkBufferx2];
double iSma(double price, int period, int r, int _bars, int instanceNo=0)
{
if (period<=1) return(price);
if (ArrayRange(workSma,0)!= _bars) ArrayResize(workSma,_bars); instanceNo *= 2; int k;
//
//
//
//
//
workSma[r][instanceNo+0] = price;
workSma[r][instanceNo+1] = price; for(k=1; k<period && (r-k)>=0; k++) workSma[r][instanceNo+1] += workSma[r-k][instanceNo+0];
workSma[r][instanceNo+1] /= 1.0*k;
return(workSma[r][instanceNo+1]);
}
//
//
//
//
//
double workEma[][_maWorkBufferx1];
double iEma(double price, double period, int r, int _bars, int instanceNo=0)
{
if (period<=1) return(price);
if (ArrayRange(workEma,0)!= _bars) ArrayResize(workEma,_bars);
//
//
//
//
//
workEma[r][instanceNo] = price;
double alpha = 2.0 / (1.0+period);
if (r>0)
workEma[r][instanceNo] = workEma[r-1][instanceNo]+alpha*(price-workEma[r-1][instanceNo]);
return(workEma[r][instanceNo]);
}
//
//
//
//
//
double workSmma[][_maWorkBufferx1];
double iSmma(double price, double period, int r, int _bars, int instanceNo=0)
{
if (period<=1) return(price);
if (ArrayRange(workSmma,0)!= _bars) ArrayResize(workSmma,_bars);
//
//
//
//
//
if (r<period)
workSmma[r][instanceNo] = price;
else workSmma[r][instanceNo] = workSmma[r-1][instanceNo]+(price-workSmma[r-1][instanceNo])/period;
return(workSmma[r][instanceNo]);
}
//
//
//
//
//
double workLwma[][_maWorkBufferx1];
double iLwma(double price, double period, int r, int _bars, int instanceNo=0)
{
if (period<=1) return(price);
if (ArrayRange(workLwma,0)!= _bars) ArrayResize(workLwma,_bars);
//
//
//
//
//
workLwma[r][instanceNo] = price;
double sumw = period;
double sum = period*price;
for(int k=1; k<period && (r-k)>=0; k++)
{
double weight = period-k;
sumw += weight;
sum += weight*workLwma[r-k][instanceNo];
}
return(sum/sumw);
}
//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
string getIndicatorName()
{
string progPath = MQL5InfoString(MQL5_PROGRAM_PATH); int start=-1;
while (true)
{
int foundAt = StringFind(progPath,"\\",start+1);
if (foundAt>=0)
start = foundAt;
else break;
}
string indicatorName = StringSubstr(progPath,start+1);
indicatorName = StringSubstr(indicatorName,0,StringLen(indicatorName)-4);
return(indicatorName);
}
//
//
//
//
//
int _tfsPer[]={PERIOD_M1,PERIOD_M2,PERIOD_M3,PERIOD_M4,PERIOD_M5,PERIOD_M6,PERIOD_M10,PERIOD_M12,PERIOD_M15,PERIOD_M20,PERIOD_M30,PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,PERIOD_D1,PERIOD_W1,PERIOD_MN1};
string _tfsStr[]={"1 minute","2 minutes","3 minutes","4 minutes","5 minutes","6 minutes","10 minutes","12 minutes","15 minutes","20 minutes","30 minutes","1 hour","2 hours","3 hours","4 hours","6 hours","8 hours","12 hours","daily","weekly","monthly"};
string periodToString(int period)
{
if (period==PERIOD_CURRENT)
period = _Period;
int i; for(i=0;i<ArraySize(_tfsPer);i++) if(period==_tfsPer[i]) break;
return(_tfsStr[i]);
}
Binary file not shown.
@@ -31,15 +31,10 @@ int ma_high_handle;
int ma_low_handle;
int period;
//
//
//
#include <AZ-INVEST/SDK/RangeBarIndicator.mqh>
RangeBarIndicator rangeBarsIndicator;
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//
//
//+------------------------------------------------------------------+
@@ -100,39 +95,42 @@ int OnCalculate(const int rates_total,
// Process data through MedianRenko indicator
//
if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,time))
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,time,close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(close))
return(0);
//
// Make the following modifications in the code below:
//
// rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated
// customChartIndicator.GetPrevCalculated() should be used instead of prev_calculated
//
// rangeBarsIndicator.Open[] should be used instead of open[]
// rangeBarsIndicator.Low[] should be used instead of low[]
// rangeBarsIndicator.High[] should be used instead of high[]
// rangeBarsIndicator.Close[] should be used instead of close[]
// customChartIndicator.Open[] should be used instead of open[]
// customChartIndicator.Low[] should be used instead of low[]
// customChartIndicator.High[] should be used instead of high[]
// customChartIndicator.Close[] should be used instead of close[]
//
// rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed
// customChartIndicator.IsNewBar (true/false) informs you if a renko brick completed
//
// rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used
// customChartIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) customChartIndicator.SetGetTimeFlag() must be called in OnInit() for customChartIndicator.Time[] to be used
//
// rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[]
// rangeBarsIndicator.Real_volume[] should be used instead of Volume[]
// (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
// customChartIndicator.Tick_volume[] should be used instead of TickVolume[]
// customChartIndicator.Real_volume[] should be used instead of Volume[]
// (!) customChartIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
//
// rangeBarsIndicator.Price[] should be used instead of Price[]
// (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used
// customChartIndicator.Price[] should be used instead of Price[]
// (!) customChartIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for customChartIndicator.Price[] to be used
//
int _prev_calculated = rangeBarsIndicator.GetPrevCalculated();
int _prev_calculated = customChartIndicator.GetPrevCalculated();
//
//
//
ArraySetAsSeries(rangeBarsIndicator.Close,true);
ArraySetAsSeries(customChartIndicator.Close,true);
//---
int limit;
if(rates_total<_prev_calculated || _prev_calculated<=0)
@@ -154,8 +152,8 @@ int OnCalculate(const int rates_total,
{
TrendBuffer[i]=TrendBuffer[i+1];
//---
if(NormalizeDouble(rangeBarsIndicator.Close[i],_Digits)>NormalizeDouble(MaHighBuffer[i+1],_Digits)) TrendBuffer[i]=1;
if(NormalizeDouble(rangeBarsIndicator.Close[i],_Digits)<NormalizeDouble(MaLowBuffer[i+1],_Digits)) TrendBuffer[i]=-1;
if(NormalizeDouble(customChartIndicator.Close[i],_Digits)>NormalizeDouble(MaHighBuffer[i+1],_Digits)) TrendBuffer[i]=1;
if(NormalizeDouble(customChartIndicator.Close[i],_Digits)<NormalizeDouble(MaLowBuffer[i+1],_Digits)) TrendBuffer[i]=-1;
//---
if(TrendBuffer[i]<0)
{
Binary file not shown.
Binary file not shown.
+395
View File
@@ -0,0 +1,395 @@
//+------------------------------------------------------------------+
//| HalfTrend.mq5 |
//| Copyright 2020, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 10
#property indicator_plots 6
//--- plot
#property indicator_label1 "UP"
#property indicator_color1 MediumOrchid // up[] DodgerBlue
#property indicator_type1 DRAW_LINE
#property indicator_width1 2
#property indicator_label2 "DN"
#property indicator_color2 Red // down[]
#property indicator_type2 DRAW_LINE
#property indicator_width2 2
#property indicator_label3 "ATR-LOW"
#property indicator_color3 Red // atrlo[],atrhi[]
#property indicator_type3 DRAW_LINE //
#property indicator_width3 1
#property indicator_label4 "ATR-HIGH"
#property indicator_color4 MediumOrchid // atrlo[],atrhi[]
#property indicator_type4 DRAW_LINE //From Histogram
#property indicator_width4 1
#property indicator_label5 "ARR-UP"
#property indicator_color5 MediumOrchid // arrdwn[]
#property indicator_type5 DRAW_ARROW
#property indicator_width5 1
#property indicator_label6 "ARR-DN"
#property indicator_color6 Red // arrup[]
#property indicator_type6 DRAW_ARROW
#property indicator_width6 1
input int Diamond = 2;
input int ChannelDeviation = 2;
input bool ShowChannels = true;
input bool ShowArrows = true;
input bool alertsOn = false;
input bool alertsOnCurrent = false;
input bool alertsMessage = true;
input bool alertsSound = true;
input bool alertsEmail = false;
input int lookback = 256; // Maximum lookback period
bool nexttrend;
double minhighprice, maxlowprice;
double up[], down[], atrlo[], atrhi[], trend[];
double arrup[], arrdwn[];
//int ind_mahi, ind_malo, ind_atr;
//double iMAHigh[], iMALow[], iATRx[];
#include <AZ-INVEST/CustomBarConfig.mqh>
#include <AZ-INVEST/SDK/IndicatorAccess.mqh>
#include <IncOnRingBuffer\CATROnRingBuffer.mqh>
#include <IncOnRingBuffer\CMAOnRingBuffer.mqh>
CIndicatorAccess iAccess;
CATROnRingBuffer atr;
CMAOnRingBuffer maHigh;
CMAOnRingBuffer maLow;
//iMAHigh, iMALow, iATRx
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int OnInit()
{
SetIndexBuffer(0, up, INDICATOR_DATA);
SetIndexBuffer(1, down, INDICATOR_DATA);
SetIndexBuffer(2, atrlo, INDICATOR_DATA);
SetIndexBuffer(3, atrhi, INDICATOR_DATA);
SetIndexBuffer(4, arrup, INDICATOR_DATA);
SetIndexBuffer(5, arrdwn, INDICATOR_DATA);
SetIndexBuffer(6, trend, INDICATOR_CALCULATIONS);
// SetIndexBuffer(7, iMAHigh, INDICATOR_CALCULATIONS);
// SetIndexBuffer(8, iMALow, INDICATOR_CALCULATIONS);
// SetIndexBuffer(9, iATRx, INDICATOR_CALCULATIONS);
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);
PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0.0);
ArraySetAsSeries(up, true);
ArraySetAsSeries(down, true);
ArraySetAsSeries(atrlo, true);
ArraySetAsSeries(atrhi, true);
ArraySetAsSeries(arrup, true);
ArraySetAsSeries(arrdwn, true);
ArraySetAsSeries(trend, true);
// ArraySetAsSeries(iMAHigh, true);
// ArraySetAsSeries(iMALow, true);
// ArraySetAsSeries(iATRx, true);
if(ShowChannels)
{
PlotIndexSetInteger(2,PLOT_LINE_COLOR,0,clrDodgerBlue);
PlotIndexSetInteger(3,PLOT_LINE_COLOR,0,clrRed);
PlotIndexSetInteger(2,PLOT_LINE_STYLE,STYLE_DOT);
PlotIndexSetInteger(3,PLOT_LINE_STYLE,STYLE_DOT);
}
else
{
PlotIndexSetInteger(2,PLOT_LINE_COLOR,0,clrNONE);
PlotIndexSetInteger(3,PLOT_LINE_COLOR,0,clrNONE);
}
if(ShowArrows)
{
bool rep5= PlotIndexSetInteger(4, PLOT_DRAW_TYPE, DRAW_ARROW);
bool rep6=PlotIndexSetInteger(5, PLOT_DRAW_TYPE, DRAW_ARROW);
PlotIndexSetInteger(4, PLOT_ARROW, 233); //233
PlotIndexSetInteger(5, PLOT_ARROW, 234); //234
//Comment(ShowArrows +"\n"+rep5 +"\n"+ rep6);
}
else
{ PlotIndexSetInteger(4, PLOT_DRAW_TYPE, DRAW_NONE);
PlotIndexSetInteger(5, PLOT_DRAW_TYPE, DRAW_NONE);
}
//ind_mahi = iMA(NULL, 0, Diamond, 0, MODE_SMA, PRICE_HIGH);
//ind_malo = iMA(NULL, 0, Diamond, 0, MODE_SMA, PRICE_LOW);
//ind_atr = iATR(NULL, 0, 100);
//if(ind_mahi == INVALID_HANDLE || ind_mahi == INVALID_HANDLE || ind_atr == INVALID_HANDLE)
// {
// PrintFormat("Failed to create handle of the indicators, error code %d", GetLastError());
// return(INIT_FAILED);
//}
customChartIndicator.SetGetTimeFlag();
if(!atr.Init(100,MODE_SMA,lookback))
{
PrintFormat("Failed to create ATR on ring buffer");
return(INIT_FAILED);
}
if(!maHigh.Init(Diamond, MODE_SMA, lookback))
{
PrintFormat("Failed to create maHigh on ring buffer");
return(INIT_FAILED);
}
if(!maLow.Init(Diamond, MODE_SMA, lookback))
{
PrintFormat("Failed to create maLow on ring buffer");
return(INIT_FAILED);
}
nexttrend = 0;
minhighprice = iHigh(NULL, 0, Bars(NULL, 0) - 1); // ?
maxlowprice = iLow(NULL, 0, Bars(NULL, 0) - 1); // ?
return (INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| |`
//+------------------------------------------------------------------+
int OnCalculate(
const int rates_total, // size of input time series
const int prev_calculated, // number of handled bars at the previous call
const datetime& time[], // Time array
const double& open[], // Open array
const double& high[], // High array
const double& low[], // Low array
const double& close[], // Close array
const long& tick_volume[], // Tick Volume array
const long& volume[], // Real Volume array
const int& spread[] // Spread array
)
{
//
// Process data through custom chart indicator
//
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,time,close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(close))
return(0);
int _prev_calculated = customChartIndicator.GetPrevCalculated();
int _rates_total = ArraySize(customChartIndicator.Close);
//
int i, limit, to_copy;
double _atr, lowprice_i, highprice_i, lowma, highma;
ArraySetAsSeries(customChartIndicator.Time, true);
ArraySetAsSeries(customChartIndicator.High, true);
ArraySetAsSeries(customChartIndicator.Low, true);
ArraySetAsSeries(customChartIndicator.Close, true);
if(_prev_calculated > _rates_total || _prev_calculated < 0) to_copy = _rates_total;
else
{
to_copy = _rates_total - _prev_calculated;
if(_prev_calculated > 0)
to_copy += 10;
}
// if(!RefreshBuffers(iMAHigh, iMALow, iATRx, ind_mahi, ind_malo, ind_atr, to_copy))
// return(0);
atr.MainOnArray(_rates_total,_prev_calculated,customChartIndicator.High,customChartIndicator.Low,customChartIndicator.Close);
maHigh.MainOnArray(_rates_total, _prev_calculated, customChartIndicator.High);
maLow.MainOnArray(_rates_total, _prev_calculated, customChartIndicator.Low);
//
if(_prev_calculated == 0)
limit = _rates_total - 2;
else
limit = _rates_total - _prev_calculated + 1;
for(i = limit; i >= 0; i--)
{
//lowprice_i = iLow(NULL, 0, iLowest(NULL, 0, MODE_LOW, Diamond, i));
//highprice_i = iHigh(NULL, 0, iHighest(NULL, 0, MODE_HIGH, Diamond, i));
//lowma = NormalizeDouble(iMALow[i], _Digits);
//highma = NormalizeDouble(iMAHigh[i], _Digits);
lowprice_i = customChartIndicator.Low[iAccess.Lowest(customChartIndicator.Low, Diamond, i)];
highprice_i = customChartIndicator.High[iAccess.Highest(customChartIndicator.High, Diamond, i)];
lowma = NormalizeDouble(maLow[i], _Digits);
highma = NormalizeDouble(maHigh[i], _Digits);
//
trend[i] = trend[i + 1];
//atr = iATRx[i] / 2;
_atr = atr[i] / 2;
arrup[i] = EMPTY_VALUE;
arrdwn[i] = EMPTY_VALUE;
if(trend[i + 1] != 1.0)
{
maxlowprice = MathMax(lowprice_i, maxlowprice);
if(highma < maxlowprice && customChartIndicator.Close[i] < customChartIndicator.Low[i + 1])
{
trend[i] = 1.0;
nexttrend = 0;
minhighprice = highprice_i;
}
}
else
{
minhighprice = MathMin(highprice_i, minhighprice);
if(lowma > minhighprice && customChartIndicator.Close[i] > customChartIndicator.High[i + 1])
{
trend[i] = 0.0;
nexttrend = 1;
maxlowprice = lowprice_i;
}
}
//---
if(trend[i] == 0.0)
{
if(trend[i + 1] != 0.0)
{
up[i] = down[i + 1];
up[i + 1] = up[i];
arrup[i] = up[i] - 2 * _atr;
}
else
{
up[i] = MathMax(maxlowprice, up[i + 1]);
}
atrhi[i] = up[i] + ChannelDeviation*_atr;
atrlo[i] = up[i] - ChannelDeviation*_atr;
down[i] = 0.0;
}
else
{
if(trend[i + 1] != 1.0)
{
down[i] = up[i + 1];
down[i + 1] = down[i];
arrdwn[i] = down[i] + 2 * _atr;
}
else
{
down[i] = MathMin(minhighprice, down[i + 1]);
}
atrhi[i] = down[i] + ChannelDeviation*_atr;
atrlo[i] = down[i] - ChannelDeviation*_atr;
up[i] = 0.0;
}
}
manageAlerts();
return (rates_total);
}
/*
//+------------------------------------------------------------------+
//| Filling indicator buffers from the indicators |
//+------------------------------------------------------------------+
bool RefreshBuffers(double &hi_buffer[],
double &lo_buffer[],
double &atr_buffer[],
int hi_handle,
int lo_handle,
int atr_handle,
int amount
)
{
//--- reset error code
ResetLastError();
//--- fill a part of the iMACDBuffer array with values from the indicator buffer that has 0 index
if(CopyBuffer(hi_handle, 0, 0, amount, hi_buffer) < 0)
{
//--- if the copying fails, tell the error code
PrintFormat("Failed to copy data from the MaHigh indicator, error code %d", GetLastError());
//--- quit with zero result - it means that the indicator is considered as not calculated
return(false);
}
//--- fill a part of the SignalBuffer array with values from the indicator buffer that has index 1
if(CopyBuffer(lo_handle, 0, 0, amount, lo_buffer) < 0)
{
//--- if the copying fails, tell the error code
PrintFormat("Failed to copy data from the MaLow indicator, error code %d", GetLastError());
//--- quit with zero result - it means that the indicator is considered as not calculated
return(false);
}
//--- fill a part of the StdDevBuffer array with values from the indicator buffer
if(CopyBuffer(atr_handle, 0, 0, amount, atr_buffer) < 0)
{
//--- if the copying fails, tell the error code
PrintFormat("Failed to copy data from the ATR indicator, error code %d", GetLastError());
//--- quit with zero result - it means that the indicator is considered as not calculated
return(false);
}
//--- everything is fine
return(true);
}
*/
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void manageAlerts()
{
int whichBar;
if (alertsOn)
{
if (alertsOnCurrent)
whichBar = 0;
else
whichBar = 1;
if (arrup[whichBar] != EMPTY_VALUE) doAlert(whichBar, "up");
if (arrdwn[whichBar] != EMPTY_VALUE) doAlert(whichBar, "down");
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void doAlert(int forBar, string doWhat)
{
static string previousAlert = "nothing";
static datetime previousTime;
string message;
if (previousAlert != doWhat || previousTime != iTime(NULL, 0, forBar))
{
previousAlert = doWhat;
previousTime = iTime(NULL, 0, forBar);
message = StringFormat("%s at %s", Symbol(), TimeToString(TimeLocal(), TIME_SECONDS), " HalfTrend signal ", doWhat);
if (alertsMessage) Alert(message);
if (alertsEmail) SendMail(Symbol(), StringFormat("HalfTrend %s", message));
if (alertsSound) PlaySound("alert2.wav");
}
}
//+------------------------------------------------------------------+
Binary file not shown.
@@ -20,15 +20,10 @@ double ExtLBuffer[];
double ExtCBuffer[];
double ExtColorBuffer[];
//
//
//
#include <AZ-INVEST/SDK/RangeBarIndicator.mqh>
RangeBarIndicator rangeBarsIndicator;
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//
//
//+------------------------------------------------------------------+
@@ -70,33 +65,36 @@ int OnCalculate(const int rates_total,
// Process data through MedianRenko indicator
//
if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,time))
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,time,close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(close))
return(0);
//
// Make the following modifications in the code below:
//
// rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated
// customChartIndicator.GetPrevCalculated() should be used instead of prev_calculated
//
// rangeBarsIndicator.Open[] should be used instead of open[]
// rangeBarsIndicator.Low[] should be used instead of low[]
// rangeBarsIndicator.High[] should be used instead of high[]
// rangeBarsIndicator.Close[] should be used instead of close[]
// customChartIndicator.Open[] should be used instead of open[]
// customChartIndicator.Low[] should be used instead of low[]
// customChartIndicator.High[] should be used instead of high[]
// customChartIndicator.Close[] should be used instead of close[]
//
// rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed
// customChartIndicator.IsNewBar (true/false) informs you if a renko brick completed
//
// rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used
// customChartIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) customChartIndicator.SetGetTimeFlag() must be called in OnInit() for customChartIndicator.Time[] to be used
//
// rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[]
// rangeBarsIndicator.Real_volume[] should be used instead of Volume[]
// (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
// customChartIndicator.Tick_volume[] should be used instead of TickVolume[]
// customChartIndicator.Real_volume[] should be used instead of Volume[]
// (!) customChartIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
//
// rangeBarsIndicator.Price[] should be used instead of Price[]
// (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used
// customChartIndicator.Price[] should be used instead of Price[]
// (!) customChartIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for customChartIndicator.Price[] to be used
//
int _prev_calculated = rangeBarsIndicator.GetPrevCalculated();
int _prev_calculated = customChartIndicator.GetPrevCalculated();
//
//
@@ -106,10 +104,10 @@ int OnCalculate(const int rates_total,
if(_prev_calculated==0)
{
//--- set first candle
ExtLBuffer[0]=rangeBarsIndicator.Low[0];
ExtHBuffer[0]=rangeBarsIndicator.High[0];
ExtOBuffer[0]=rangeBarsIndicator.Open[0];
ExtCBuffer[0]=rangeBarsIndicator.Close[0];
ExtLBuffer[0]=customChartIndicator.Low[0];
ExtHBuffer[0]=customChartIndicator.High[0];
ExtOBuffer[0]=customChartIndicator.Open[0];
ExtCBuffer[0]=customChartIndicator.Close[0];
limit=1;
}
else limit=_prev_calculated-1;
@@ -118,9 +116,9 @@ int OnCalculate(const int rates_total,
for(i=limit;i<rates_total && !IsStopped();i++)
{
double haOpen=(ExtOBuffer[i-1]+ExtCBuffer[i-1])/2;
double haClose=(rangeBarsIndicator.Open[i]+rangeBarsIndicator.High[i]+rangeBarsIndicator.Low[i]+rangeBarsIndicator.Close[i])/4;
double haHigh=MathMax(rangeBarsIndicator.High[i],MathMax(haOpen,haClose));
double haLow=MathMin(rangeBarsIndicator.Low[i],MathMin(haOpen,haClose));
double haClose=(customChartIndicator.Open[i]+customChartIndicator.High[i]+customChartIndicator.Low[i]+customChartIndicator.Close[i])/4;
double haHigh=MathMax(customChartIndicator.High[i],MathMax(haOpen,haClose));
double haLow=MathMin(customChartIndicator.Low[i],MathMin(haOpen,haClose));
ExtLBuffer[i]=haLow;
ExtHBuffer[i]=haHigh;
Binary file not shown.
@@ -33,15 +33,10 @@ double ExtSpanABuffer[];
double ExtSpanBBuffer[];
double ExtChikouBuffer[];
//
//
//
#include <AZ-INVEST/SDK/RangeBarIndicator.mqh>
RangeBarIndicator rangeBarsIndicator;
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//
//
//+------------------------------------------------------------------+
@@ -118,33 +113,36 @@ int OnCalculate(const int rates_total,
// Process data through MedianRenko indicator
//
if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,time))
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,time,close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(close))
return(0);
//
// Make the following modifications in the code below:
//
// rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated
// customChartIndicator.GetPrevCalculated() should be used instead of prev_calculated
//
// rangeBarsIndicator.Open[] should be used instead of open[]
// rangeBarsIndicator.Low[] should be used instead of low[]
// rangeBarsIndicator.High[] should be used instead of high[]
// rangeBarsIndicator.Close[] should be used instead of close[]
// customChartIndicator.Open[] should be used instead of open[]
// customChartIndicator.Low[] should be used instead of low[]
// customChartIndicator.High[] should be used instead of high[]
// customChartIndicator.Close[] should be used instead of close[]
//
// rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed
// customChartIndicator.IsNewBar (true/false) informs you if a renko brick completed
//
// rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used
// customChartIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) customChartIndicator.SetGetTimeFlag() must be called in OnInit() for customChartIndicator.Time[] to be used
//
// rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[]
// rangeBarsIndicator.Real_volume[] should be used instead of Volume[]
// (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
// customChartIndicator.Tick_volume[] should be used instead of TickVolume[]
// customChartIndicator.Real_volume[] should be used instead of Volume[]
// (!) customChartIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
//
// rangeBarsIndicator.Price[] should be used instead of Price[]
// (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used
// customChartIndicator.Price[] should be used instead of Price[]
// (!) customChartIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for customChartIndicator.Price[] to be used
//
int _prev_calculated = rangeBarsIndicator.GetPrevCalculated();
int _prev_calculated = customChartIndicator.GetPrevCalculated();
//
//
@@ -157,20 +155,20 @@ int OnCalculate(const int rates_total,
//---
for(int i=limit;i<rates_total && !IsStopped();i++)
{
ExtChikouBuffer[i]=rangeBarsIndicator.Close[i];
ExtChikouBuffer[i]=customChartIndicator.Close[i];
//--- tenkan sen
double _high=Highest(rangeBarsIndicator.High,InpTenkan,i);
double _low=Lowest(rangeBarsIndicator.Low,InpTenkan,i);
double _high=Highest(customChartIndicator.High,InpTenkan,i);
double _low=Lowest(customChartIndicator.Low,InpTenkan,i);
ExtTenkanBuffer[i]=(_high+_low)/2.0;
//--- kijun sen
_high=Highest(rangeBarsIndicator.High,InpKijun,i);
_low=Lowest(rangeBarsIndicator.Low,InpKijun,i);
_high=Highest(customChartIndicator.High,InpKijun,i);
_low=Lowest(customChartIndicator.Low,InpKijun,i);
ExtKijunBuffer[i]=(_high+_low)/2.0;
//--- senkou span a
ExtSpanABuffer[i]=(ExtTenkanBuffer[i]+ExtKijunBuffer[i])/2.0;
//--- senkou span b
_high=Highest(rangeBarsIndicator.High,InpSenkou,i);
_low=Lowest(rangeBarsIndicator.Low,InpSenkou,i);
_high=Highest(customChartIndicator.High,InpSenkou,i);
_low=Lowest(customChartIndicator.Low,InpSenkou,i);
ExtSpanBBuffer[i]=(_high+_low)/2.0;
}
//--- done
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+96
View File
@@ -0,0 +1,96 @@
#property description "Linear Regression"
#property description "https://www.mql5.com/en/articles/270"
#property copyright "ds2"
#property version "1.0"
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
#property indicator_type1 DRAW_LINE
#property indicator_color1 Cyan
//+------------------------------------------------------------------+
input int LRPeriod = 20; // Bars in regression
//+------------------------------------------------------------------+
// The main buffer - drawing a line on a chart
double ExtLRBuffer[];
//
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//+------------------------------------------------------------------+
void OnInit()
{
SetIndexBuffer(0, ExtLRBuffer, INDICATOR_DATA);
PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, LRPeriod-1);
IndicatorSetString (INDICATOR_SHORTNAME,"Linear Regression");
IndicatorSetInteger(INDICATOR_DIGITS,_Digits+1);
customChartIndicator.SetUseAppliedPriceFlag(PRICE_CLOSE);
}
//+------------------------------------------------------------------+
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 &TickVolume[],
const long &Volume[],
const int &Spread[])
{
////////////////////////////////////////////////////////////////////////
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,Time,Close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(Close))
return(0);
int _prev_calculated = customChartIndicator.GetPrevCalculated();
////////////////////////////////////////////////////////////////////////
if (rates_total < LRPeriod)
return(0);
int limit = _prev_calculated ? _prev_calculated-1 : LRPeriod-1;
// The cycle along the calculated bars
for (int bar = limit; bar < rates_total; bar++)
{
double lrvalue = 0; // the linear regression value in this bar
double Sx=0, Sy=0, Sxy=0, Sxx=0;
// Finding intermediate values-sums
Sx = 0;
Sy = 0;
Sxx = 0;
Sxy = 0;
for (int x = 1; x <= LRPeriod; x++)
{
double y = customChartIndicator.GetPrice(bar-LRPeriod+x);
Sx += x;
Sy += y;
Sxx += x*x;
Sxy += x*y;
}
// Regression ratios
double a = (LRPeriod * Sxy - Sx * Sy) / (LRPeriod * Sxx - Sx * Sx);
double b = (Sy - a * Sx) / LRPeriod;
lrvalue = a*LRPeriod + b;
// Saving regression results
ExtLRBuffer[bar] = lrvalue;
}
return(rates_total);
}
//+------------------------------------------------------------------+
Binary file not shown.
@@ -21,15 +21,10 @@ input ENUM_APPLIED_PRICE InpAppliedPrice=PRICE_CLOSE;
//--- indicator buffers
double ExtLineBuffer[];
//
//
//
#include <AZ-INVEST/SDK/RangeBarIndicator.mqh>
RangeBarIndicator rangeBarsIndicator;
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//
//
//+------------------------------------------------------------------+
@@ -169,7 +164,7 @@ void OnInit()
// Indicator uses Price[] array for calculations so we need to set this in the MedianRenkoIndicator class
//
rangeBarsIndicator.SetUseAppliedPriceFlag(InpAppliedPrice);
customChartIndicator.SetUseAppliedPriceFlag(InpAppliedPrice);
//
//
@@ -200,33 +195,36 @@ int OnCalculate(const int rates_total,const int prev_calculated,
// Process data through MedianRenko indicator
//
if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,Time))
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,Time,Close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(Close))
return(0);
//
// Make the following modifications in the code below:
//
// rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated
// customChartIndicator.GetPrevCalculated() should be used instead of prev_calculated
//
// rangeBarsIndicator.Open[] should be used instead of open[]
// rangeBarsIndicator.Low[] should be used instead of low[]
// rangeBarsIndicator.High[] should be used instead of high[]
// rangeBarsIndicator.Close[] should be used instead of close[]
// customChartIndicator.Open[] should be used instead of open[]
// customChartIndicator.Low[] should be used instead of low[]
// customChartIndicator.High[] should be used instead of high[]
// customChartIndicator.Close[] should be used instead of close[]
//
// rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed
// customChartIndicator.IsNewBar (true/false) informs you if a renko brick completed
//
// rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used
// customChartIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) customChartIndicator.SetGetTimeFlag() must be called in OnInit() for customChartIndicator.Time[] to be used
//
// rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[]
// rangeBarsIndicator.Real_volume[] should be used instead of Volume[]
// (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
// customChartIndicator.Tick_volume[] should be used instead of TickVolume[]
// customChartIndicator.Real_volume[] should be used instead of Volume[]
// (!) customChartIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
//
// rangeBarsIndicator.Price[] should be used instead of Price[]
// (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used
// customChartIndicator.Price[] should be used instead of Price[]
// (!) customChartIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for customChartIndicator.Price[] to be used
//
int _prev_calculated = rangeBarsIndicator.GetPrevCalculated();
int _prev_calculated = customChartIndicator.GetPrevCalculated();
int _begin = 0;
//
@@ -246,10 +244,10 @@ int OnCalculate(const int rates_total,const int prev_calculated,
//--- calculation
switch(InpMAMethod)
{
case MODE_EMA: CalculateEMA(rates_total,_prev_calculated,_begin,rangeBarsIndicator.Price); break;
case MODE_LWMA: CalculateLWMA(rates_total,_prev_calculated,_begin,rangeBarsIndicator.Price); break;
case MODE_SMMA: CalculateSmoothedMA(rates_total,_prev_calculated,_begin,rangeBarsIndicator.Price); break;
case MODE_SMA: CalculateSimpleMA(rates_total,_prev_calculated,_begin,rangeBarsIndicator.Price); break;
case MODE_EMA: CalculateEMA(rates_total,_prev_calculated,_begin,customChartIndicator.Price); break;
case MODE_LWMA: CalculateLWMA(rates_total,_prev_calculated,_begin,customChartIndicator.Price); break;
case MODE_SMMA: CalculateSmoothedMA(rates_total,_prev_calculated,_begin,customChartIndicator.Price); break;
case MODE_SMA: CalculateSimpleMA(rates_total,_prev_calculated,_begin,customChartIndicator.Price); break;
}
//--- return value of prev_calculated for next call
return(rates_total);
Binary file not shown.
@@ -35,17 +35,11 @@ double ExtFastMaBuffer[];
double ExtSlowMaBuffer[];
double ExtMacdBuffer[];
//
//
//
#include <AZ-INVEST/SDK/RangeBarIndicator.mqh>
RangeBarIndicator rangeBarsIndicator;
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//
//
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
@@ -80,27 +74,43 @@ int OnCalculate(const int rates_total,const int prev_calculated,
const int &Spread[])
{
//
// Precoess data through MedianRenko indicator
// Process data through MedianRenko indicator
//
if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,Time))
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,Time,Close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(Close))
return(0);
//
// Make the following modifications in the code below:
//
// rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated
// rangeBarsIndicator.Open[] should be used instead of open[]
// rangeBarsIndicator.Low[] should be used instead of low[]
// rangeBarsIndicator.High[] should be used instead of high[]
// rangeBarsIndicator.Close[] should be used instead of close[]
// customChartIndicator.GetPrevCalculated() should be used instead of prev_calculated
//
int _prev_calculated = rangeBarsIndicator.GetPrevCalculated();
// customChartIndicator.Open[] should be used instead of open[]
// customChartIndicator.Low[] should be used instead of low[]
// customChartIndicator.High[] should be used instead of high[]
// customChartIndicator.Close[] should be used instead of close[]
//
// customChartIndicator.IsNewBar (true/false) informs you if a renko brick completed
//
// customChartIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) customChartIndicator.SetGetTimeFlag() must be called in OnInit() for customChartIndicator.Time[] to be used
//
// customChartIndicator.Tick_volume[] should be used instead of TickVolume[]
// customChartIndicator.Real_volume[] should be used instead of Volume[]
// (!) customChartIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
//
// customChartIndicator.Price[] should be used instead of Price[]
// (!) customChartIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for customChartIndicator.Price[] to be used
//
int _prev_calculated = customChartIndicator.GetPrevCalculated();
//
//
//
//
//--- check for data
if(rates_total<InpSignalSMA)
@@ -115,16 +125,17 @@ int OnCalculate(const int rates_total,const int prev_calculated,
}
//--- get Fast EMA buffer
if(IsStopped()) return(0); //Checking for stop flag
ExponentialMAOnBuffer(rates_total,_prev_calculated,0,InpFastEMA,rangeBarsIndicator.Close,ExtFastMaBuffer);
ExponentialMAOnBuffer(rates_total,_prev_calculated,0,InpFastEMA,customChartIndicator.Close,ExtFastMaBuffer);
//--- get SlowSMA buffer
if(IsStopped()) return(0); //Checking for stop flag
ExponentialMAOnBuffer(rates_total,_prev_calculated,0,InpSlowEMA,rangeBarsIndicator.Close,ExtSlowMaBuffer);
ExponentialMAOnBuffer(rates_total,_prev_calculated,0,InpSlowEMA,customChartIndicator.Close,ExtSlowMaBuffer);
//---
int limit;
if(_prev_calculated==0)
limit=0;
else limit=_prev_calculated-1;
//--- calculate MACD
for(int i=limit;i<rates_total && !IsStopped();i++)
{
ExtMacdBuffer[i] = ExtFastMaBuffer[i]-ExtSlowMaBuffer[i];
Binary file not shown.
+132
View File
@@ -0,0 +1,132 @@
//+------------------------------------------------------------------+
//| MACD.mq5 |
//| Copyright 2009, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link "http://www.mql5.com"
#property description "Moving Average Convergence/Divergence"
#include <MovingAverages.mqh>
//--- indicator settings
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_plots 2
#property indicator_type1 DRAW_LINE
#property indicator_type2 DRAW_LINE
#property indicator_color1 clrMagenta
#property indicator_color2 clrBlue
#property indicator_width1 2
#property indicator_width2 2
#property indicator_label1 "Main"
#property indicator_label2 "Signal"
//--- input parameters
input int InpFastEMA=12; // Fast EMA period
input int InpSlowEMA=26; // Slow EMA period
input int InpSignalSMA=9; // Signal SMA period
//--- indicator buffers
//double ExtMacdBufferUp[];
//double ExtMacdBufferDn[];
double ExtSignalBuffer[];
double ExtFastMaBuffer[];
double ExtSlowMaBuffer[];
double ExtMacdBuffer[];
//
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
void OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,ExtMacdBuffer,INDICATOR_DATA);
SetIndexBuffer(1,ExtSignalBuffer,INDICATOR_DATA);
//SetIndexBuffer(2,ExtSignalBuffer,INDICATOR_DATA);
SetIndexBuffer(2,ExtFastMaBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(3,ExtSlowMaBuffer,INDICATOR_CALCULATIONS);
//SetIndexBuffer(4,ExtMacdBuffer,INDICATOR_CALCULATIONS);
//--- sets first bar from what index will be drawn
PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,InpSignalSMA-1);
//--- name for Dindicator subwindow label
IndicatorSetString(INDICATOR_SHORTNAME,"MACD("+string(InpFastEMA)+","+string(InpSlowEMA)+","+string(InpSignalSMA)+")");
//--- initialization done
}
//+------------------------------------------------------------------+
//| Moving Averages Convergence/Divergence |
//+------------------------------------------------------------------+
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 &TickVolume[],
const long &Volume[],
const int &Spread[])
{
//
// Precoess data through MedianRenko indicator
//
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,Time,Close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(Close))
return(0);
int _prev_calculated = customChartIndicator.GetPrevCalculated();
//
//
//
//--- check for data
if(rates_total<InpSignalSMA)
return(0);
//--- we can copy not all data
int to_copy;
if(_prev_calculated>rates_total || _prev_calculated<0) to_copy=rates_total;
else
{
to_copy=rates_total-_prev_calculated;
if(_prev_calculated>0) to_copy++;
}
//--- get Fast EMA buffer
if(IsStopped()) return(0); //Checking for stop flag
ExponentialMAOnBuffer(rates_total,_prev_calculated,0,InpFastEMA,customChartIndicator.Close,ExtFastMaBuffer);
//--- get SlowSMA buffer
if(IsStopped()) return(0); //Checking for stop flag
ExponentialMAOnBuffer(rates_total,_prev_calculated,0,InpSlowEMA,customChartIndicator.Close,ExtSlowMaBuffer);
//---
int limit;
if(_prev_calculated==0)
limit=0;
else limit=_prev_calculated-1;
//--- calculate MACD
for(int i=limit;i<rates_total && !IsStopped();i++)
{
ExtMacdBuffer[i] = ExtFastMaBuffer[i]-ExtSlowMaBuffer[i];
/*
if(ExtMacdBuffer[i] > 0)
{
ExtMacdBufferUp[i] = ExtFastMaBuffer[i]-ExtSlowMaBuffer[i];
ExtMacdBufferDn[i] = 0;
}
else if(ExtMacdBuffer[i] < 0)
{
ExtMacdBufferDn[i] = ExtFastMaBuffer[i]-ExtSlowMaBuffer[i];
ExtMacdBufferUp[i] = 0;
}
*/
}
//--- calculate Signal
SimpleMAOnBuffer(rates_total,_prev_calculated,0,InpSignalSMA,ExtMacdBuffer,ExtSignalBuffer);
//--- OnCalculate done. Return new _prev_calculated.
return(rates_total);
}
//+------------------------------------------------------------------+
Binary file not shown.
@@ -21,16 +21,12 @@ double ExtMomentumBuffer[];
//--- global variable
int ExtMomentumPeriod;
//
//
//
#include <AZ-INVEST/SDK/RangeBarIndicator.mqh>
RangeBarIndicator rangeBarsIndicator;
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//
//
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
@@ -40,7 +36,7 @@ void OnInit()
// Indicator uses Price[] array for calculations so we need to set this in the MedianRenkoIndicator class
//
rangeBarsIndicator.SetUseAppliedPriceFlag(InpApplyToPrice);
customChartIndicator.SetUseAppliedPriceFlag(InpApplyToPrice);
//
//
@@ -91,33 +87,36 @@ int OnCalculate(const int rates_total,const int prev_calculated,
// Process data through MedianRenko indicator
//
if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,Time))
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,Time,Close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(Close))
return(0);
//
// Make the following modifications in the code below:
//
// rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated
// customChartIndicator.GetPrevCalculated() should be used instead of prev_calculated
//
// rangeBarsIndicator.Open[] should be used instead of open[]
// rangeBarsIndicator.Low[] should be used instead of low[]
// rangeBarsIndicator.High[] should be used instead of high[]
// rangeBarsIndicator.Close[] should be used instead of close[]
// customChartIndicator.Open[] should be used instead of open[]
// customChartIndicator.Low[] should be used instead of low[]
// customChartIndicator.High[] should be used instead of high[]
// customChartIndicator.Close[] should be used instead of close[]
//
// rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed
// customChartIndicator.IsNewBar (true/false) informs you if a renko brick completed
//
// rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used
// customChartIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) customChartIndicator.SetGetTimeFlag() must be called in OnInit() for customChartIndicator.Time[] to be used
//
// rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[]
// rangeBarsIndicator.Real_volume[] should be used instead of Volume[]
// (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
// customChartIndicator.Tick_volume[] should be used instead of TickVolume[]
// customChartIndicator.Real_volume[] should be used instead of Volume[]
// (!) customChartIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
//
// rangeBarsIndicator.Price[] should be used instead of Price[]
// (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used
// customChartIndicator.Price[] should be used instead of Price[]
// (!) customChartIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for customChartIndicator.Price[] to be used
//
int _prev_calculated = rangeBarsIndicator.GetPrevCalculated();
int _prev_calculated = customChartIndicator.GetPrevCalculated();
//
//
@@ -137,8 +136,8 @@ int OnCalculate(const int rates_total,const int prev_calculated,
//--- main cycle
for(int i=pos;i<rates_total && !IsStopped();i++)
{
if(rangeBarsIndicator.Price[i-ExtMomentumPeriod] > 0)
ExtMomentumBuffer[i]=rangeBarsIndicator.Price[i]*100/rangeBarsIndicator.Price[i-ExtMomentumPeriod];
if(customChartIndicator.Price[i-ExtMomentumPeriod] > 0)
ExtMomentumBuffer[i]=customChartIndicator.Price[i]*100/customChartIndicator.Price[i-ExtMomentumPeriod];
}
//--- OnCalculate done. Return new prev_calculated.
Binary file not shown.
+233
View File
@@ -0,0 +1,233 @@
//+------------------------------------------------------------------+
//| iNRTR.mq5 |
//| MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "MetaQuotes Software Corp."
#property link "http://www.mql5.com"
#property version "1.00"
#property indicator_chart_window
#property indicator_buffers 6
#property indicator_plots 4
//--- plot Support
#property indicator_label1 "Support"
#property indicator_type1 DRAW_ARROW
#property indicator_color1 DodgerBlue
#property indicator_style1 STYLE_SOLID
#property indicator_width1 2
//--- plot Resistance
#property indicator_label2 "Resistance"
#property indicator_type2 DRAW_ARROW
#property indicator_color2 Red
#property indicator_style2 STYLE_SOLID
#property indicator_width2 2
//--- plot UpTarget
#property indicator_label3 "UpTarget"
#property indicator_type3 DRAW_ARROW
#property indicator_color3 RoyalBlue
#property indicator_style3 STYLE_SOLID
#property indicator_width3 2
//--- plot DnTarget
#property indicator_label4 "DnTarget"
#property indicator_type4 DRAW_ARROW
#property indicator_color4 Crimson
#property indicator_style4 STYLE_SOLID
#property indicator_width4 2
//--- input parameters
input int period = 40; /*period*/ // ATR period in bars
input double k = 2.0; /*k*/ // ATR change coefficient
//--- indicator buffers
double SupportBuffer[];
double ResistanceBuffer[];
double UpTargetBuffer[];
double DnTargetBuffer[];
double Trend[];
double ATRBuffer[];
int Handle;
//
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,SupportBuffer,INDICATOR_DATA);
PlotIndexSetInteger(0,PLOT_ARROW,159);
SetIndexBuffer(1,ResistanceBuffer,INDICATOR_DATA);
PlotIndexSetInteger(1,PLOT_ARROW,159);
SetIndexBuffer(2,UpTargetBuffer,INDICATOR_DATA);
PlotIndexSetInteger(2,PLOT_ARROW,158);
SetIndexBuffer(3,DnTargetBuffer,INDICATOR_DATA);
PlotIndexSetInteger(3,PLOT_ARROW,158);
SetIndexBuffer(4,Trend,INDICATOR_DATA);
SetIndexBuffer(5,ATRBuffer,INDICATOR_CALCULATIONS);
PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0);
PlotIndexSetDouble(2,PLOT_EMPTY_VALUE,0);
PlotIndexSetDouble(3,PLOT_EMPTY_VALUE,0);
PlotIndexSetDouble(4,PLOT_EMPTY_VALUE,0);
PlotIndexSetDouble(5,PLOT_EMPTY_VALUE,0);
Handle=iATR(_Symbol,PERIOD_CURRENT,period);
//---
return(0);
}
//+------------------------------------------------------------------+
//| 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[]
)
{
//
// Process data through MedianRenko indicator
//
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,time,close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(close))
return(0);
//
// Make the following modifications in the code below:
//
// customChartIndicator.GetPrevCalculated() should be used instead of prev_calculated
//
// customChartIndicator.Open[] should be used instead of open[]
// customChartIndicator.Low[] should be used instead of low[]
// customChartIndicator.High[] should be used instead of high[]
// customChartIndicator.Close[] should be used instead of close[]
//
// customChartIndicator.IsNewBar (true/false) informs you if a renko brick completed
//
// customChartIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) customChartIndicator.SetGetTimeFlag() must be called in OnInit() for customChartIndicator.Time[] to be used
//
// customChartIndicator.Tick_volume[] should be used instead of TickVolume[]
// customChartIndicator.Real_volume[] should be used instead of Volume[]
// (!) customChartIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
//
// customChartIndicator.Price[] should be used instead of Price[]
// (!) customChartIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for customChartIndicator.Price[] to be used
//
int _prev_calculated = customChartIndicator.GetPrevCalculated();
//
//
//
static bool error=true;
int start;
if(_prev_calculated==0)
{
error=true;
}
if(error)
{
ArrayInitialize(Trend,0);
ArrayInitialize(UpTargetBuffer,0);
ArrayInitialize(DnTargetBuffer,0);
ArrayInitialize(SupportBuffer,0);
ArrayInitialize(ResistanceBuffer,0);
start=period;
error=false;
}
else
{
start=_prev_calculated-1;
}
if(CopyBuffer(Handle,0,0,rates_total-start,ATRBuffer)==-1)
{
error=true;
return(0);
}
for(int i=start;i<rates_total;i++)
{
Trend[i]=Trend[i-1];
UpTargetBuffer[i]=UpTargetBuffer[i-1];
DnTargetBuffer[i]=DnTargetBuffer[i-1];
SupportBuffer[i]=SupportBuffer[i-1];
ResistanceBuffer[i]=ResistanceBuffer[i-1];
switch((int)Trend[i])
{
case 2:
if(customChartIndicator.Low[i]>UpTargetBuffer[i])
{
UpTargetBuffer[i]=customChartIndicator.Close[i];
SupportBuffer[i]=customChartIndicator.Close[i]-k*ATRBuffer[i];
}
if(customChartIndicator.Close[i]<SupportBuffer[i])
{
DnTargetBuffer[i]=customChartIndicator.Close[i];
ResistanceBuffer[i]=customChartIndicator.Close[i]+k*ATRBuffer[i];
Trend[i]=3;
UpTargetBuffer[i]=0;
SupportBuffer[i]=0;
}
break;
case 3:
if(customChartIndicator.High[i]<DnTargetBuffer[i])
{
DnTargetBuffer[i]=customChartIndicator.Close[i];
ResistanceBuffer[i]=customChartIndicator.Close[i]+k*ATRBuffer[i];
}
if(customChartIndicator.Close[i]>ResistanceBuffer[i])
{
UpTargetBuffer[i]=customChartIndicator.Close[i];
SupportBuffer[i]=customChartIndicator.Close[i]-k*ATRBuffer[i];
Trend[i]=2;
DnTargetBuffer[i]=0;
ResistanceBuffer[i]=0;
}
break;
case 0:
UpTargetBuffer[i]=customChartIndicator.Close[i];
DnTargetBuffer[i]=customChartIndicator.Close[i];
Trend[i]=1;
break;
case 1:
if(customChartIndicator.Low[i]>UpTargetBuffer[i])
{
UpTargetBuffer[i]=customChartIndicator.Close[i];
SupportBuffer[i]=customChartIndicator.Close[i]-k*ATRBuffer[i];
Trend[i]=2;
DnTargetBuffer[i]=0;
}
if(customChartIndicator.High[i]<DnTargetBuffer[i])
{
DnTargetBuffer[i]=customChartIndicator.Close[i];
ResistanceBuffer[i]=customChartIndicator.Close[i]+k*ATRBuffer[i];
Trend[i]=3;
UpTargetBuffer[i]=0;
}
break;
}
}
return(rates_total);
}
//+------------------------------------------------------------------+
Binary file not shown.
+117
View File
@@ -0,0 +1,117 @@
//+------------------------------------------------------------------+
//| OBV.mq5 |
//| Copyright 2009-2017, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009-2017, MetaQuotes Software Corp."
#property link "http://www.mql5.com"
#property description "On Balance Volume"
//--- indicator settings
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots 1
#property indicator_type1 DRAW_LINE
#property indicator_color1 DodgerBlue
#property indicator_label1 "OBV"
//--- input parametrs
input ENUM_APPLIED_VOLUME InpVolumeType=VOLUME_TICK; // Volumes
//---- indicator buffer
double ExtOBVBuffer[];
//
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//+------------------------------------------------------------------+
//| On Balance Volume initialization function |
//+------------------------------------------------------------------+
void OnInit()
{
//--- define indicator buffer
SetIndexBuffer(0,ExtOBVBuffer);
//--- set indicator digits
IndicatorSetInteger(INDICATOR_DIGITS,0);
//---- OnInit done
customChartIndicator.SetGetVolumesFlag();
}
//+------------------------------------------------------------------+
//| On Balance Volume |
//+------------------------------------------------------------------+
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[])
{
//
// Process data through MedianRenko indicator
//
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,time,close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(close))
return(0);
int _prev_calculated = customChartIndicator.GetPrevCalculated();
//
//
//
//--- variables
int pos;
//--- check for bars count
if(rates_total<2)
return(0);
//--- starting calculation
pos=_prev_calculated-1;
//--- correct position, when it's first iteration
if(pos<1)
{
pos=1;
if(InpVolumeType==VOLUME_TICK)
ExtOBVBuffer[0]=(double)customChartIndicator.Tick_volume[0];
else ExtOBVBuffer[0]=(double)customChartIndicator.Real_volume[0];
}
//--- main cycle
if(InpVolumeType==VOLUME_TICK)
CalculateOBV(pos,rates_total,customChartIndicator.Close,customChartIndicator.Tick_volume);
else
CalculateOBV(pos,rates_total,customChartIndicator.Close,customChartIndicator.Real_volume);
//---- OnCalculate done. Return new prev_calculated.
return(rates_total);
}
//+------------------------------------------------------------------+
//| Calculate OBV by volume argument |
//+------------------------------------------------------------------+
void CalculateOBV(int StartPosition,
int RatesCount,
const double &ClBuffer[],
const long &VolBuffer[])
{
for(int i=StartPosition;i<RatesCount && !IsStopped();i++)
{
//--- get some data
double Volume=(double)VolBuffer[i];
double PrevClose=ClBuffer[i-1];
double CurrClose=ClBuffer[i];
//--- fill ExtOBVBuffer
if(CurrClose<PrevClose) ExtOBVBuffer[i]=ExtOBVBuffer[i-1]-Volume;
else
{
if(CurrClose>PrevClose) ExtOBVBuffer[i]=ExtOBVBuffer[i-1]+Volume;
else ExtOBVBuffer[i]=ExtOBVBuffer[i-1];
}
}
}
//+------------------------------------------------------------------+
Binary file not shown.
+679
View File
@@ -0,0 +1,679 @@
//+------------------------------------------------------------------+
//| Oscillator Candles.mq5 |
//| Copyright 2015, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property description"Oscillator Candles by pipPod"
#property version "1.00"
#property indicator_separate_window
#property indicator_buffers 7
#property indicator_plots 1
//---
#property indicator_type1 DRAW_COLOR_CANDLES
#property indicator_color1 clrLimeGreen,clrFireBrick
//---
#property indicator_levelcolor clrLightSlateGray
//---
double indicator_level1= 0;
double indicator_level2= 20;
double indicator_level3= 30;
double indicator_level4= 50;
double indicator_level5= 70;
double indicator_level6= 80;
double indicator_level7= 100;
double indicator_level8=-100;
//---
#include <MovingAverages.mqh>
#include <AZ-INVEST/CustomBarConfig.mqh>
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum indicators
{
INDICATOR_MACD, //Moving Average Convergence/Divergence
INDICATOR_STOCHASTIC, //Stochastic Oscillator
INDICATOR_RSI, //Relative Strength Index
INDICATOR_CCI, //Commodity Channel Index
INDICATOR_MOMENTUM, //Momentum Index
};
//--- indicator to show
input indicators Indicator=INDICATOR_MACD;
//--- indicator parameters
input string MACD;
input ushort FastEMA=12; //Fast EMA Period
input ushort SlowEMA=26; //Slow EMA Period
//---
input string Stochastic;
input ushort Kperiod=7; //K Period
input ushort Slowing=3;
input ENUM_STO_PRICE PriceField=STO_LOWHIGH; //Price Field
//---
input string RSI;
input ushort RSIPeriod=14; //RSI Period
//---
input string CCI;
input ushort CCIPeriod=14; //CCI Period
//---
input string Momentum;
input ushort MomPeriod=14; //Momentum Period
//---
input string _; //---
input bool PriceLine=true; //Horizontal Value Line
#define priceLine "priceLine"
input bool AutoColor=false;//Auto Color Candles
//---index buffers for drawing candles
double OpenBuffer[];
double HighBuffer[];
double LowBuffer[];
double CloseBuffer[];
double ColorBuffer[];
//---Stochastic buffers
double HighesBuffer[];
double LowestBuffer[];
//---CCI buffers
double PriceBuffer[];
double MovAvBuffer[];
//---
long chartID=ChartID();
short window;
#define OBJ_NONE -1
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
string shortName;
switch(Indicator)
{
case INDICATOR_MACD:
shortName=StringFormat("MACD(%d,%d)",FastEMA,SlowEMA);
IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
IndicatorSetInteger(INDICATOR_LEVELS,1);
IndicatorSetDouble(INDICATOR_LEVELVALUE,0,indicator_level1);
PlotIndexSetString(0,PLOT_LABEL,"MACD Open;MACD High;MACD Low;MACD Close");
for(int i=0;i<5;i++)
PlotIndexSetInteger(i,PLOT_DRAW_BEGIN,SlowEMA-1);
break;
case INDICATOR_STOCHASTIC:
shortName=StringFormat("Stochastic(%d,%d)",Kperiod,Slowing);
SetIndexBuffer(5,HighesBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(6,LowestBuffer,INDICATOR_CALCULATIONS);
IndicatorSetInteger(INDICATOR_DIGITS,0);
IndicatorSetInteger(INDICATOR_LEVELS,3);
IndicatorSetDouble(INDICATOR_LEVELVALUE,0,indicator_level2);
IndicatorSetDouble(INDICATOR_LEVELVALUE,1,indicator_level4);
IndicatorSetDouble(INDICATOR_LEVELVALUE,2,indicator_level6);
PlotIndexSetString(0,PLOT_LABEL,"Stoch Open;Stoch High;Stoch Low;Stoch Close");
for(int i=0;i<5;i++)
PlotIndexSetInteger(i,PLOT_DRAW_BEGIN,Kperiod-1+Slowing-1);
break;
case INDICATOR_RSI:
shortName=StringFormat("RSI(%d)",RSIPeriod);
IndicatorSetInteger(INDICATOR_DIGITS,0);
IndicatorSetInteger(INDICATOR_LEVELS,3);
IndicatorSetDouble(INDICATOR_LEVELVALUE,0,indicator_level3);
IndicatorSetDouble(INDICATOR_LEVELVALUE,1,indicator_level4);
IndicatorSetDouble(INDICATOR_LEVELVALUE,2,indicator_level5);
PlotIndexSetString(0,PLOT_LABEL,"RSI Open;RSI High;RSI Low;RSI Close");
for(int i=0;i<5;i++)
PlotIndexSetInteger(i,PLOT_DRAW_BEGIN,RSIPeriod-1);
break;
case INDICATOR_CCI:
shortName=StringFormat("CCI(%d)",CCIPeriod);
SetIndexBuffer(5,PriceBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(6,MovAvBuffer,INDICATOR_CALCULATIONS);
IndicatorSetInteger(INDICATOR_DIGITS,0);
IndicatorSetInteger(INDICATOR_LEVELS,3);
IndicatorSetDouble(INDICATOR_LEVELVALUE,0,indicator_level1);
IndicatorSetDouble(INDICATOR_LEVELVALUE,1,indicator_level7);
IndicatorSetDouble(INDICATOR_LEVELVALUE,2,indicator_level8);
PlotIndexSetString(0,PLOT_LABEL,"CCI Open;CCI High;CCI Low;CCI Close");
for(int i=0;i<5;i++)
PlotIndexSetInteger(i,PLOT_DRAW_BEGIN,CCIPeriod-1);
break;
case INDICATOR_MOMENTUM:
shortName=StringFormat("Momentum(%d)",MomPeriod);
IndicatorSetInteger(INDICATOR_DIGITS,2);
IndicatorSetInteger(INDICATOR_LEVELS,1);
IndicatorSetDouble(INDICATOR_LEVELVALUE,0,indicator_level7);
PlotIndexSetString(0,PLOT_LABEL,"Mom Open;Mom High;Mom Low;Mom Close");
for(int i=0;i<5;i++)
PlotIndexSetInteger(i,PLOT_DRAW_BEGIN,MomPeriod-1);
}
//---set name, get window
IndicatorSetString(INDICATOR_SHORTNAME,shortName);
window=(short)ChartWindowFind(chartID,shortName);
//---index buffers
SetIndexBuffer(0,OpenBuffer,INDICATOR_DATA);
SetIndexBuffer(1,HighBuffer,INDICATOR_DATA);
SetIndexBuffer(2,LowBuffer,INDICATOR_DATA);
SetIndexBuffer(3,CloseBuffer,INDICATOR_DATA);
SetIndexBuffer(4,ColorBuffer,INDICATOR_COLOR_INDEX);
//---color bars
if(AutoColor)
SetColors();
//---delete price line
if(!PriceLine && ObjectFind(chartID,priceLine)!=OBJ_NONE)
ObjectDelete(chartID,priceLine);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| 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[])
{
//
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,time,close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(close))
return(0);
int _prev_calculated = customChartIndicator.GetPrevCalculated();
//
//---bars to count
int toFill=rates_total-_prev_calculated;
if(_prev_calculated>0)
toFill++;
//---fill OHLC buffers
switch(Indicator)
{
case INDICATOR_MACD:
if(MACD(customChartIndicator.GetRatesTotal(),_prev_calculated,customChartIndicator.High,customChartIndicator.Low,customChartIndicator.Close)!=toFill)
return(0);
break;
case INDICATOR_STOCHASTIC:
if(Stochastic(customChartIndicator.GetRatesTotal(),_prev_calculated,customChartIndicator.High,customChartIndicator.Low,customChartIndicator.Close)!=toFill)
return(0);
break;
case INDICATOR_RSI:
if(RSI(customChartIndicator.GetRatesTotal(),_prev_calculated,customChartIndicator.High,customChartIndicator.Low,customChartIndicator.Close)!=toFill)
return(0);
break;
case INDICATOR_CCI:
if(CCI(customChartIndicator.GetRatesTotal(),_prev_calculated,customChartIndicator.High,customChartIndicator.Low,customChartIndicator.Close)!=toFill)
return(0);
break;
case INDICATOR_MOMENTUM:
if(Momentum(customChartIndicator.GetRatesTotal(),_prev_calculated,customChartIndicator.High,customChartIndicator.Low,customChartIndicator.Close)!=toFill)
return(0);
}
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
//| Moving Average Convergence/Divergence |
//+------------------------------------------------------------------+
int MACD(const int rates_total,
const int prev_calculated,
const double &high[],
const double &low[],
const double &close[])
{
//---check bars and input vars
if(rates_total<=SlowEMA || FastEMA<=1 || SlowEMA<FastEMA)
return(0);
//---declare vars
int begin,count=0;
double highFast,highSlow,
lowFast,lowSlow,
closeFast,closeSlow;
static double prevCloseFast,prevCloseSlow;
//--- initial zero
if(prev_calculated==0)
{
for(int i=0;i<SlowEMA && !IsStopped();i++)
{
OpenBuffer[i]=HighBuffer[i]=LowBuffer[i]=CloseBuffer[i]=0.0;
count++;
}
begin=SlowEMA;
}
else
begin=prev_calculated-1;
//--- calculate MACD
for(int i=begin;i<rates_total && !IsStopped();i++)
{
highFast = ExponentialMA(i,FastEMA,prevCloseFast,high);
highSlow = ExponentialMA(i,SlowEMA,prevCloseSlow,high);
lowFast = ExponentialMA(i,FastEMA,prevCloseFast,low);
lowSlow = ExponentialMA(i,SlowEMA,prevCloseSlow,low);
closeFast = ExponentialMA(i,FastEMA,prevCloseFast,close);
closeSlow = ExponentialMA(i,SlowEMA,prevCloseSlow,close);
//---fill OHLC buffers
HighBuffer[i]= highFast-highSlow;
LowBuffer[i] = lowFast-lowSlow;
CloseBuffer[i]=closeFast-closeSlow;
//---check for new bar
static int k;
if(k!=i)
{
prevCloseFast = closeFast;
prevCloseSlow = closeSlow;
OpenBuffer[i] = CloseBuffer[i-1];
k=i;
}
//---set candle color
ColorBuffer[i]=(CloseBuffer[i]>OpenBuffer[i])?0:1;
//---horizontal value line
if(PriceLine)
PriceLine(CloseBuffer[i]);
count++;
}
//--- macd done. return count.
return(count);
}
//+------------------------------------------------------------------+
//| Stochastic Oscillator |
//+------------------------------------------------------------------+
int Stochastic(const int rates_total,
const int prev_calculated,
const double &high[],
const double &low[],
const double &close[])
{
//--- check for bars count
if(rates_total<=Kperiod+Slowing || Kperiod<=1)
return(0);
//--- declare variables
int begin,count=0;
double sumLowH,sumLowL,sumLowC,sumHigh;
double min,max;
//---
begin=Kperiod-1;
if(begin<prev_calculated)
begin=prev_calculated-1;
else
for(int i=0;i<begin && !IsStopped();i++)
LowestBuffer[i]=HighesBuffer[i]=0.0;
//--- calculate HighesBuffer[] and LowestBuffer[]
for(int i=begin;i<rates_total && !IsStopped();i++)
{
min = 1000000.0;
max =-1000000.0;
for(int k=(i-Kperiod+1);k<=i;k++)
{
switch(PriceField)
{
case STO_LOWHIGH:
if(min>low[k])
min=low[k];
if(max<high[k])
max=high[k];
break;
case STO_CLOSECLOSE:
if(min>close[k])
min=close[k];
if(max<close[k])
max=close[k];
}
}
LowestBuffer[i] = min;
HighesBuffer[i] = max;
}
//--- %K
begin=Kperiod-1;
if(begin<prev_calculated)
begin=prev_calculated-1;
else
for(int i=0;i<begin && !IsStopped();i++)
{
OpenBuffer[i]=HighBuffer[i]=LowBuffer[i]=CloseBuffer[i]=0.0;
count++;
}
//--- main cycle
for(int i=begin;i<rates_total && !IsStopped();i++)
{
sumLowH=sumLowL=sumLowC=sumHigh=0.0;
for(int k=(i-Slowing+1);k<=i;k++)
{
sumLowH += (high[i]-LowestBuffer[k]);
sumLowL += (low[i]-LowestBuffer[k]);
sumLowC += (close[k]-LowestBuffer[k]);
sumHigh += (HighesBuffer[k]-LowestBuffer[k]);
}
//---check for new bar
static int k;
if(k!=i)
{
OpenBuffer[i]=CloseBuffer[i-1];
k=i;
}
//---check zero divide and fill candle buffers
if(sumHigh==0.0)
HighBuffer[i]=LowBuffer[i]=CloseBuffer[i]=50.0;
else
{
HighBuffer[i]= OpenBuffer[i]+(sumLowH/sumHigh*100-OpenBuffer[i])/Slowing;
LowBuffer[i] = OpenBuffer[i]+(sumLowL/sumHigh*100-OpenBuffer[i])/Slowing;
CloseBuffer[i]=sumLowC/sumHigh*100;
}
//---set candle color
ColorBuffer[i]=(CloseBuffer[i]>OpenBuffer[i])?0:1;
//---horizontal value line
if(PriceLine)
PriceLine(CloseBuffer[i]);
count++;
}
//--- stochastic done. return count.
return(count);
}
//+------------------------------------------------------------------+
//| Relative Strength index |
//+------------------------------------------------------------------+
int RSI(const int rates_total,
const int prev_calculated,
const double &high[],
const double &low[],
const double &close[])
{
//--- check bars and input vars
if(rates_total<=RSIPeriod || RSIPeriod<=1)
return(0);
int begin,count=0;
//--- declare vars
double diffC,
diffH,
diffL;
double currPositive = 0.0,
currNegative = 0.0;
static double prevPositive = 0.0,
prevNegative = 0.0;
//--- preliminary calculations
begin=prev_calculated-1;
if(begin<=RSIPeriod)
{
//--- first RSIPeriod values of the indicator are not calculated
OpenBuffer[0]=HighBuffer[0]=LowBuffer[0]=CloseBuffer[0]=0.0;
double sumPositive = 0.0,
sumNegative = 0.0;
count++;
for(int i=1;i<=RSIPeriod && !IsStopped();i++)
{
OpenBuffer[i]=HighBuffer[i]=LowBuffer[i]=CloseBuffer[i]=0.0;
diffC=close[i]-close[i-1];
sumPositive += (diffC>0.0? diffC:0.0);
sumNegative += (diffC<0.0?-diffC:0.0);
count++;
}
//--- calculate first visible value
currPositive = sumPositive/RSIPeriod;
currNegative = sumNegative/RSIPeriod;
//--- check zero divide, calculate first rsi and fill candle buffers
if(currNegative!=0.0)
OpenBuffer[RSIPeriod]=HighBuffer[RSIPeriod]=LowBuffer[RSIPeriod]=
CloseBuffer[RSIPeriod]=100.0-100.0/(1.0+currPositive/currNegative);
else
if(currPositive!=0.0)
OpenBuffer[RSIPeriod]=HighBuffer[RSIPeriod]=LowBuffer[RSIPeriod]=
CloseBuffer[RSIPeriod]=100.0;
else
OpenBuffer[RSIPeriod]=HighBuffer[RSIPeriod]=LowBuffer[RSIPeriod]=
CloseBuffer[RSIPeriod]=50.0;
prevPositive = currPositive;
prevNegative = currNegative;
//--- prepare the position value for main calculation
begin=RSIPeriod+1;
}
//--- the main loop of calculations
for(int i=begin;i<rates_total && !IsStopped();i++)
{
diffC = close[i]-close[i-1];
diffH = (high[i]-close[i-1])/RSIPeriod;
diffL = (low[i]-close[i-1])/RSIPeriod;
currPositive = (prevPositive*(RSIPeriod-1)+(diffC>0.0? diffC:0.0))/RSIPeriod;
currNegative = (prevNegative*(RSIPeriod-1)+(diffC<0.0?-diffC:0.0))/RSIPeriod;
//--- check zero divide, calculate rsi and fill candle buffers
if(prevNegative!=0.0)
{
HighBuffer[i]= 100.0-100.0/(1.0+(prevPositive+diffH)/prevNegative);
LowBuffer[i] = 100.0-100.0/(1.0+prevPositive/(prevNegative-diffL));
}
else
if(prevPositive!=0.0)
HighBuffer[i]= LowBuffer[i] = 100.0;
else
HighBuffer[i]=LowBuffer[i]=50.0;
if(currNegative!=0.0)
CloseBuffer[i]=100.0-100.0/(1.0+currPositive/currNegative);
else
if(currPositive!=0.0)
CloseBuffer[i]=100.0;
else
CloseBuffer[i]=50.0;
//---check for new bar
static int k;
if(k!=i)
{
prevPositive = currPositive;
prevNegative = currNegative;
OpenBuffer[i]= CloseBuffer[i-1];
k=i;
}
//---set candle color
ColorBuffer[i]=(CloseBuffer[i]>OpenBuffer[i])?0:1;
//---horizontal value line
if(PriceLine)
PriceLine(CloseBuffer[i]);
count++;
}
//---rsi done.return count.
return(count);
}
//+------------------------------------------------------------------+
//| Commodity Channel Index |
//+------------------------------------------------------------------+
int CCI(const int rates_total,
const int prev_calculated,
const double &high[],
const double &low[],
const double &close[])
{
//--- check bars and input vars
if(rates_total<=CCIPeriod || CCIPeriod<=1)
return(0);
//--- declare vars
int begin,count=0;
double sum,mul;
//--- initial zero
if(prev_calculated<1)
{
for(int i=0;i<CCIPeriod-1 && !IsStopped();i++)
{
OpenBuffer[i]=HighBuffer[i]=LowBuffer[i]=CloseBuffer[i]=0.0;
PriceBuffer[i] = (high[i]+low[i]+close[i])/3;
MovAvBuffer[i] = 0.0;
count++;
}
}
//--- calculate position
begin=prev_calculated-1;
if(begin<CCIPeriod-1)
begin=CCIPeriod-1;
//--- typical price and its moving average
for(int i=begin;i<rates_total && !IsStopped();i++)
{
PriceBuffer[i] = (high[i]+low[i]+close[i])/3;
MovAvBuffer[i] = SimpleMA(i,CCIPeriod,PriceBuffer);
}
//--- standard deviations and cci counting
mul=0.015/CCIPeriod;
begin=prev_calculated-1;
if(begin<CCIPeriod-1)
begin=CCIPeriod-1;
//---
for(int i=begin;i<rates_total && !IsStopped();i++)
{
sum=0.0;
int k=i-CCIPeriod+1;
while(k<=i)
{
sum+=MathAbs(PriceBuffer[k]-MovAvBuffer[i]);
k++;
}
sum*=mul;
//---check zero divide and fill candle buffers
if(sum==0.0)
HighBuffer[i]=LowBuffer[i]=CloseBuffer[i]=0.0;
else
{
HighBuffer[i]=(high[i]-MovAvBuffer[i])/sum;
LowBuffer[i] =(low[i]-MovAvBuffer[i])/sum;
CloseBuffer[i]=(close[i]-MovAvBuffer[i])/sum;
}
//---check for new bar
static int m;
if(m!=i)
{
OpenBuffer[i]=CloseBuffer[i-1];
m=i;
}
//---set candle color
ColorBuffer[i]=(CloseBuffer[i]>OpenBuffer[i])?0:1;
//---horizontal value line
if(PriceLine)
PriceLine(CloseBuffer[i]);
count++;
}
//---cci done. return count.
return(count);
}
//+------------------------------------------------------------------+
//| Momentum |
//+------------------------------------------------------------------+
int Momentum(const int rates_total,
const int prev_calculated,
const double &high[],
const double &low[],
const double &close[])
{
//--- check bars and input param
if(rates_total<=MomPeriod || MomPeriod<=0)
return(0);
int begin,count=0;
//--- initial zero
if(prev_calculated<=0)
{
for(int i=0;i<MomPeriod && !IsStopped();i++)
{
OpenBuffer[i]=HighBuffer[i]=LowBuffer[i]=CloseBuffer[i]=0.0;
count++;
}
begin=MomPeriod;
}
else
begin=prev_calculated-1;
static double closeMomPeriod;
//--- the main loop of calculations
for(int i=begin;i<rates_total && !IsStopped();i++)
{
//---check for new bar
static int k;
if(k!=i)
{
closeMomPeriod= close[i-MomPeriod];
// if(closeMomPeriod == 0)
// continue;
if(closeMomPeriod == 0)
closeMomPeriod = 1;
OpenBuffer[i] = CloseBuffer[i-1];
k=i;
}
HighBuffer[i]= high[i]*100/closeMomPeriod;
LowBuffer[i] = low[i]*100/closeMomPeriod;
CloseBuffer[i]=close[i]*100/closeMomPeriod;
//---set candle color
ColorBuffer[i]=(CloseBuffer[i]>OpenBuffer[i])?0:1;
//---horizontal value line
if(PriceLine)
PriceLine(CloseBuffer[i]);
count++;
}
//--- momentum done. return count
return(count);
}
//+------------------------------------------------------------------+
//| Horizontal value line |
//+------------------------------------------------------------------+
void PriceLine(const double &close_price)
{
if(ObjectFind(chartID,priceLine)!=OBJ_NONE)
ObjectDelete(chartID,priceLine);
if(!ObjectCreate(chartID,priceLine,OBJ_HLINE,window,0,close_price))
{
Print(__FUNCTION__,": error ",GetLastError());
return;
}
ObjectSetInteger(chartID,priceLine,OBJPROP_WIDTH,1);
ObjectSetInteger(chartID,priceLine,OBJPROP_STYLE,STYLE_SOLID);
ObjectSetInteger(chartID,priceLine,OBJPROP_COLOR,clrLightSlateGray);
ObjectSetInteger(chartID,priceLine,OBJPROP_HIDDEN,true);
ObjectSetInteger(chartID,priceLine,OBJPROP_SELECTABLE,false);
return;
}
//+------------------------------------------------------------------+
//| Auto colors for candles |
//+------------------------------------------------------------------+
bool SetColors()
{
color colorBase=clrNONE,
colorQote=clrNONE;
string base,
qote;
string Name[9] = {"AUD","CAD","CHF","EUR","GBP","JPY","NZD","USD","XAU"};
color Color[9] =
{
clrDarkOrange,clrWhiteSmoke,clrFireBrick,clrRoyalBlue,
clrSilver,clrYellow,clrDarkViolet,clrLimeGreen,clrGold
};
base = StringSubstr(_Symbol,0,3); //Base currency name
qote = StringSubstr(_Symbol,3,3); //Quote currency name
for(int i=0;i<9;i++)
{
if(base==Name[i])
colorBase=Color[i];
if(qote==Name[i])
colorQote=Color[i];
}
if(!PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,colorBase) ||
!PlotIndexSetInteger(0,PLOT_LINE_COLOR,1,colorQote))
return(false);
if(ChartGetInteger(0,CHART_COLOR_CANDLE_BULL)!=colorBase)
{
if(!ChartSetInteger(0,CHART_COLOR_CANDLE_BULL,colorBase) ||
!ChartSetInteger(0,CHART_COLOR_CHART_UP,colorBase))
return(false);
}
if(ChartGetInteger(0,CHART_COLOR_CANDLE_BEAR)!=colorQote)
{
if(!ChartSetInteger(0,CHART_COLOR_CANDLE_BEAR,colorQote) ||
!ChartSetInteger(0,CHART_COLOR_CHART_DOWN,colorQote))
return(false);
}
return(true);
}
//+------------------------------------------------------------------+
Binary file not shown.
@@ -24,15 +24,10 @@ bool ExtDirectionLong;
double ExtSarStep;
double ExtSarMaximum;
//
//
//
#include <AZ-INVEST/SDK/RangeBarIndicator.mqh>
RangeBarIndicator rangeBarsIndicator;
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//
//
//+------------------------------------------------------------------+
@@ -94,33 +89,36 @@ int OnCalculate(const int rates_total,
// Process data through MedianRenko indicator
//
if(!rangeBarsIndicator.OnCalculate(rates_total,prev_calculated,time))
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,time,close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(close))
return(0);
//
// Make the following modifications in the code below:
//
// rangeBarsIndicator.GetPrevCalculated() should be used instead of prev_calculated
// customChartIndicator.GetPrevCalculated() should be used instead of prev_calculated
//
// rangeBarsIndicator.Open[] should be used instead of open[]
// rangeBarsIndicator.Low[] should be used instead of low[]
// rangeBarsIndicator.High[] should be used instead of high[]
// rangeBarsIndicator.Close[] should be used instead of close[]
// customChartIndicator.Open[] should be used instead of open[]
// customChartIndicator.Low[] should be used instead of low[]
// customChartIndicator.High[] should be used instead of high[]
// customChartIndicator.Close[] should be used instead of close[]
//
// rangeBarsIndicator.IsNewBar (true/false) informs you if a renko brick completed
// customChartIndicator.IsNewBar (true/false) informs you if a renko brick completed
//
// rangeBarsIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) rangeBarsIndicator.SetGetTimeFlag() must be called in OnInit() for rangeBarsIndicator.Time[] to be used
// customChartIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) customChartIndicator.SetGetTimeFlag() must be called in OnInit() for customChartIndicator.Time[] to be used
//
// rangeBarsIndicator.Tick_volume[] should be used instead of TickVolume[]
// rangeBarsIndicator.Real_volume[] should be used instead of Volume[]
// (!) rangeBarsIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
// customChartIndicator.Tick_volume[] should be used instead of TickVolume[]
// customChartIndicator.Real_volume[] should be used instead of Volume[]
// (!) customChartIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
//
// rangeBarsIndicator.Price[] should be used instead of Price[]
// (!) rangeBarsIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for rangeBarsIndicator.Price[] to be used
// customChartIndicator.Price[] should be used instead of Price[]
// (!) customChartIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for customChartIndicator.Price[] to be used
//
int _prev_calculated = rangeBarsIndicator.GetPrevCalculated();
int _prev_calculated = customChartIndicator.GetPrevCalculated();
//
//
@@ -135,12 +133,12 @@ int OnCalculate(const int rates_total,
pos=1;
ExtAFBuffer[0]=ExtSarStep;
ExtAFBuffer[1]=ExtSarStep;
ExtSARBuffer[0]=rangeBarsIndicator.High[0];
ExtSARBuffer[0]=customChartIndicator.High[0];
ExtLastRevPos=0;
ExtDirectionLong=false;
ExtSARBuffer[1]=GetHigh(pos,ExtLastRevPos,rangeBarsIndicator.High);
ExtEPBuffer[0]=rangeBarsIndicator.Low[pos];
ExtEPBuffer[1]=rangeBarsIndicator.Low[pos];
ExtSARBuffer[1]=GetHigh(pos,ExtLastRevPos,customChartIndicator.High);
ExtEPBuffer[0]=customChartIndicator.Low[pos];
ExtEPBuffer[1]=customChartIndicator.Low[pos];
}
//---main cycle
for(int i=pos;i<rates_total-1 && !IsStopped();i++)
@@ -148,24 +146,24 @@ int OnCalculate(const int rates_total,
//--- check for reverse
if(ExtDirectionLong)
{
if(ExtSARBuffer[i]>rangeBarsIndicator.Low[i])
if(ExtSARBuffer[i]>customChartIndicator.Low[i])
{
//--- switch to SHORT
ExtDirectionLong=false;
ExtSARBuffer[i]=GetHigh(i,ExtLastRevPos,rangeBarsIndicator.High);
ExtEPBuffer[i]=rangeBarsIndicator.Low[i];
ExtSARBuffer[i]=GetHigh(i,ExtLastRevPos,customChartIndicator.High);
ExtEPBuffer[i]=customChartIndicator.Low[i];
ExtLastRevPos=i;
ExtAFBuffer[i]=ExtSarStep;
}
}
else
{
if(ExtSARBuffer[i]<rangeBarsIndicator.High[i])
if(ExtSARBuffer[i]<customChartIndicator.High[i])
{
//--- switch to LONG
ExtDirectionLong=true;
ExtSARBuffer[i]=GetLow(i,ExtLastRevPos,rangeBarsIndicator.Low);
ExtEPBuffer[i]=rangeBarsIndicator.High[i];
ExtSARBuffer[i]=GetLow(i,ExtLastRevPos,customChartIndicator.Low);
ExtEPBuffer[i]=customChartIndicator.High[i];
ExtLastRevPos=i;
ExtAFBuffer[i]=ExtSarStep;
}
@@ -174,9 +172,9 @@ int OnCalculate(const int rates_total,
if(ExtDirectionLong)
{
//--- check for new High
if(rangeBarsIndicator.High[i]>ExtEPBuffer[i-1] && i!=ExtLastRevPos)
if(customChartIndicator.High[i]>ExtEPBuffer[i-1] && i!=ExtLastRevPos)
{
ExtEPBuffer[i]=rangeBarsIndicator.High[i];
ExtEPBuffer[i]=customChartIndicator.High[i];
ExtAFBuffer[i]=ExtAFBuffer[i-1]+ExtSarStep;
if(ExtAFBuffer[i]>ExtSarMaximum)
ExtAFBuffer[i]=ExtSarMaximum;
@@ -193,15 +191,15 @@ int OnCalculate(const int rates_total,
//--- calculate SAR for tomorrow
ExtSARBuffer[i+1]=ExtSARBuffer[i]+ExtAFBuffer[i]*(ExtEPBuffer[i]-ExtSARBuffer[i]);
//--- check for SAR
if(ExtSARBuffer[i+1]>rangeBarsIndicator.Low[i] || ExtSARBuffer[i+1]>rangeBarsIndicator.Low[i-1])
ExtSARBuffer[i+1]=MathMin(rangeBarsIndicator.Low[i],rangeBarsIndicator.Low[i-1]);
if(ExtSARBuffer[i+1]>customChartIndicator.Low[i] || ExtSARBuffer[i+1]>customChartIndicator.Low[i-1])
ExtSARBuffer[i+1]=MathMin(customChartIndicator.Low[i],customChartIndicator.Low[i-1]);
}
else
{
//--- check for new Low
if(rangeBarsIndicator.Low[i]<ExtEPBuffer[i-1] && i!=ExtLastRevPos)
if(customChartIndicator.Low[i]<ExtEPBuffer[i-1] && i!=ExtLastRevPos)
{
ExtEPBuffer[i]=rangeBarsIndicator.Low[i];
ExtEPBuffer[i]=customChartIndicator.Low[i];
ExtAFBuffer[i]=ExtAFBuffer[i-1]+ExtSarStep;
if(ExtAFBuffer[i]>ExtSarMaximum)
ExtAFBuffer[i]=ExtSarMaximum;
@@ -218,8 +216,8 @@ int OnCalculate(const int rates_total,
//--- calculate SAR for tomorrow
ExtSARBuffer[i+1]=ExtSARBuffer[i]+ExtAFBuffer[i]*(ExtEPBuffer[i]-ExtSARBuffer[i]);
//--- check for SAR
if(ExtSARBuffer[i+1]<rangeBarsIndicator.High[i] || ExtSARBuffer[i+1]<rangeBarsIndicator.High[i-1])
ExtSARBuffer[i+1]=MathMax(rangeBarsIndicator.High[i],rangeBarsIndicator.High[i-1]);
if(ExtSARBuffer[i+1]<customChartIndicator.High[i] || ExtSARBuffer[i+1]<customChartIndicator.High[i-1])
ExtSARBuffer[i+1]=MathMax(customChartIndicator.High[i],customChartIndicator.High[i-1]);
}
}
//---- OnCalculate done. Return new prev_calculated.
Binary file not shown.
+245
View File
@@ -0,0 +1,245 @@
#property copyright "2017-2020, Artur Zas"
#property link "http://www.az-invest.eu"
//---- indicator settings
#property indicator_separate_window
#property indicator_buffers 7
#property indicator_plots 5
#property indicator_label1 "Volume"
#property indicator_type1 DRAW_HISTOGRAM // volume
#property indicator_color1 Gray
#property indicator_style1 0
#property indicator_width1 2
#property indicator_label2 "Buy volume"
#property indicator_type2 DRAW_HISTOGRAM // buy volume
#property indicator_color2 clrDarkGreen
#property indicator_style2 0
#property indicator_width2 2
#property indicator_label3 "Sell volume"
#property indicator_type3 DRAW_HISTOGRAM // sell volume
#property indicator_color3 clrFireBrick
#property indicator_style3 0
#property indicator_width3 2
#property indicator_label4 "Bar volume delta"
#property indicator_type4 DRAW_COLOR_HISTOGRAM // bar delta
#property indicator_color4 Lime,Red,clrNONE
#property indicator_style4 0
#property indicator_width4 5
#property indicator_label5 "Cumulative volume delta"
#property indicator_type5 DRAW_COLOR_LINE // cumulative delta
#property indicator_color5 Green, Red, clrNONE
#property indicator_style5 STYLE_DOT
#property indicator_width5 1
//--- input data
static ENUM_APPLIED_VOLUME InpVolumeType= (SymbolInfoInteger(_Symbol,SYMBOL_VOLUME) <= 0) ? VOLUME_TICK : VOLUME_REAL; // Volumes
input bool InpShowVolume = true; // Show volume histogram
input bool InpShowBuySellVolume = true; // Show bar's buy/sell volume breakdown
input bool InpShowBarDelta = true; // Show bar's buy/sell volume delta
input bool InpShowCumulativeDelta = false; // Show cumulative volume delta
input int InpCumulativeDeltaScale = 1; // Scale down cumulative volume 1:x
//---- indicator buffers
double ExtBarDeltaBuffer[];
double ExtBarDeltaColorsBuffer[];
double ExtBuyVolumeBuffer[];
double ExtSellVolumeBuffer[];
double ExtVolumeBuffer[];
double ExtCumulativeVolumeBuffer[];
double ExtCumulativeVolumeColorBuffer[];
double cumulativeDelta = 0;
//
#include <AZ-INVEST/CustomBarConfig.mqh>
//
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
void OnInit()
{
//---- buffers
SetIndexBuffer(0,ExtVolumeBuffer,INDICATOR_DATA);
SetIndexBuffer(1,ExtBuyVolumeBuffer,INDICATOR_DATA);
SetIndexBuffer(2,ExtSellVolumeBuffer,INDICATOR_DATA);
SetIndexBuffer(3,ExtBarDeltaBuffer,INDICATOR_DATA);
SetIndexBuffer(4,ExtBarDeltaColorsBuffer,INDICATOR_COLOR_INDEX);
SetIndexBuffer(5,ExtCumulativeVolumeBuffer,INDICATOR_DATA);
SetIndexBuffer(6,ExtCumulativeVolumeColorBuffer,INDICATOR_COLOR_INDEX);
//---- name for DataWindow and indicator subwindow label
IndicatorSetString(INDICATOR_SHORTNAME,"Pro Volume");
//---- indicator digits
IndicatorSetInteger(INDICATOR_DIGITS,0);
customChartIndicator.SetGetTimeFlag();
customChartIndicator.SetGetVolumesFlag();
customChartIndicator.SetGetVolumeBreakdownFlag();
//----
}
//+------------------------------------------------------------------+
//| Volumes |
//+------------------------------------------------------------------+
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 for rates total
if(rates_total<2)
return(0);
//
// Process data through MedianRenko indicator
//
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,time,close))
return(0);
if(!customChartIndicator.BufferSynchronizationCheck(close))
return(0);
//
// Make the following modifications in the code below:
//
// customChartIndicator.GetPrevCalculated() should be used instead of prev_calculated
//
// customChartIndicator.Open[] should be used instead of open[]
// customChartIndicator.Low[] should be used instead of low[]
// customChartIndicator.High[] should be used instead of high[]
// customChartIndicator.Close[] should be used instead of close[]
//
// customChartIndicator.IsNewBar (true/false) informs you if a renko brick completed
//
// customChartIndicator.Time[] shold be used instead of Time[] for checking the renko bar time.
// (!) customChartIndicator.SetGetTimeFlag() must be called in OnInit() for customChartIndicator.Time[] to be used
//
// customChartIndicator.Tick_volume[] should be used instead of TickVolume[]
// customChartIndicator.Real_volume[] should be used instead of Volume[]
// (!) customChartIndicator.SetGetVolumesFlag() must be called in OnInit() for Tick_volume[] & Real_volume[] to be used
//
// customChartIndicator.Price[] should be used instead of Price[]
// (!) customChartIndicator.SetUseAppliedPriceFlag(ENUM_APPLIED_PRICE _applied_price) must be called in OnInit() for customChartIndicator.Price[] to be used
//
int _prev_calculated = customChartIndicator.GetPrevCalculated();
//
//
//
//--- starting work
int start=_prev_calculated-1;
//--- correct position
// if(start<1) start=1;
if(start<0) start=0;
//--- main cycle
CalculateData(start,rates_total);
//--- OnCalculate done. Return new prev_calculated.
return(rates_total);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CalculateData(const int nPosition,
const int nRatesCount)
{
double volume,buyVolume,sellVolume,barDelta;
for(int i=nPosition;i<nRatesCount && !IsStopped();i++)
{
//--- calculate indicator
volume = (InpVolumeType == VOLUME_TICK) ? (double)customChartIndicator.Tick_volume[i] : (double)customChartIndicator.Real_volume[i];
buyVolume = customChartIndicator.Buy_volume[i];
sellVolume = customChartIndicator.Sell_volume[i];
barDelta = buyVolume - sellVolume;
//
if(InpShowVolume)
ExtVolumeBuffer[i] = volume;
else
ExtVolumeBuffer[i] = 0;
if(InpShowBuySellVolume)
{
ExtBuyVolumeBuffer[i] = buyVolume;
ExtSellVolumeBuffer[i] = sellVolume * (-1);
}
else
{
ExtBuyVolumeBuffer[i] = 0;
ExtSellVolumeBuffer[i] = 0;
}
if(InpShowBarDelta)
{
ExtBarDeltaBuffer[i] = barDelta;
ExtBarDeltaColorsBuffer[i] = ( ExtBarDeltaBuffer[i] < 0 ) ? 1 : (( ExtBarDeltaBuffer[i] == 0 ) ? 2 : 0 );
}
else
{
ExtBarDeltaBuffer[i] = 0;
ExtBarDeltaColorsBuffer[i] = 2;
}
if(InpShowCumulativeDelta)
{
if((i != (nRatesCount-1)) && (i>0))
{
if(IsNewDay(customChartIndicator.Time[i-1], customChartIndicator.Time[i]))
cumulativeDelta = 0; // reset cumulative volme
cumulativeDelta += barDelta;
ExtCumulativeVolumeBuffer[i] = cumulativeDelta / InpCumulativeDeltaScale;
ExtCumulativeVolumeColorBuffer[i] = ( ExtCumulativeVolumeBuffer[i] < 0 ) ? 1 : (( ExtCumulativeVolumeBuffer[i] == 0 ) ? 2 : 0 );
}
else
{
ExtCumulativeVolumeBuffer[i] = (cumulativeDelta + barDelta) / InpCumulativeDeltaScale;
ExtCumulativeVolumeColorBuffer[i] = ( ExtCumulativeVolumeBuffer[i] < 0 ) ? 1 : (( ExtCumulativeVolumeBuffer[i] == 0 ) ? 2 : 0 );
}
}
else
{
ExtCumulativeVolumeBuffer[i] = 0;
ExtCumulativeVolumeColorBuffer[i] = 2;
}
}
}
//+------------------------------------------------------------------+
bool IsNewDay(datetime prevTime,datetime currTime)
{
MqlDateTime prev;
MqlDateTime curr;
TimeToStruct(prevTime,prev);
TimeToStruct(currTime,curr);
if(prev.day_of_week != curr.day_of_week)
return true;
else
return false;
}

Some files were not shown because too many files have changed in this diff Show More