Initial comit of TrendBreakouts
This commit is contained in:
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -0,0 +1,404 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Breakout_Fractals.mq5 |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//#include "Algo_Skeleton_Functions.mqh"
|
||||
#include "Phoenix_Functions.mqh"
|
||||
|
||||
bool trailWhenMarketOpensDaily = false ;
|
||||
int OnInit()
|
||||
{
|
||||
//---
|
||||
|
||||
//---
|
||||
for(int i=0; i<NUM_MAX_ALLOWED_TRADES ; i++)
|
||||
{
|
||||
BuyActiveTradesArray[i] = NULL ;
|
||||
SellActiveTradesArray[i] = NULL ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
objectsManager.addTextTiger();
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//---
|
||||
Print("Buys Count: " + buysCount);
|
||||
Print("Sells Count: " + sellsCount);
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//---
|
||||
cleanBuyTradesArr();
|
||||
cleanSellTradesArr();
|
||||
|
||||
|
||||
|
||||
if(newCandleDetectorM5.isNewCandle())
|
||||
{
|
||||
if(APPLY_TRAIL && TRAIL_TIME_FRAME == PERIOD_M5){
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_M5);
|
||||
}
|
||||
if(TIME_FRAME_TO_TRADE == PERIOD_M5)
|
||||
{
|
||||
datetime currTime = TimeCurrent();
|
||||
Comment(TimeToString(currTime,TIME_MINUTES) + ": Sell Below: " + currentSupportLowerEdge + " Buy Above: "+ currentResistanceHighEdge);
|
||||
|
||||
string timeFrameStr = timeFrameToString(TIME_FRAME_TO_TRADE);
|
||||
|
||||
findAndDrawFractalsAndZones(TIME_FRAME_TO_TRADE,timeFrameStr);
|
||||
|
||||
if(candleClosedBelowSupportZone(TIME_FRAME_TO_TRADE)) // SELL CASE
|
||||
{
|
||||
handleSells();
|
||||
}
|
||||
|
||||
|
||||
if(candleClosedAboveResistanceZone(TIME_FRAME_TO_TRADE)) // BUY CASE
|
||||
{
|
||||
handleBuys();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(newCandleDetectorM15.isNewCandle())
|
||||
{
|
||||
if(APPLY_TRAIL && TRAIL_TIME_FRAME == PERIOD_M15){
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_M15);
|
||||
}
|
||||
if(TIME_FRAME_TO_TRADE == PERIOD_M15)
|
||||
{
|
||||
datetime currTime = TimeCurrent();
|
||||
Comment(TimeToString(currTime,TIME_MINUTES) + ": Sell Below: " + currentSupportLowerEdge + " Buy Above: "+ currentResistanceHighEdge);
|
||||
|
||||
string timeFrameStr = timeFrameToString(TIME_FRAME_TO_TRADE);
|
||||
|
||||
findAndDrawFractalsAndZones(TIME_FRAME_TO_TRADE,timeFrameStr);
|
||||
|
||||
if(candleClosedBelowSupportZone(TIME_FRAME_TO_TRADE)) // SELL CASE
|
||||
{
|
||||
handleSells();
|
||||
}
|
||||
|
||||
|
||||
if(candleClosedAboveResistanceZone(TIME_FRAME_TO_TRADE)) // BUY CASE
|
||||
{
|
||||
handleBuys();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(newCandleDetectorM30.isNewCandle())
|
||||
{
|
||||
|
||||
if(APPLY_TRAIL && TRAIL_TIME_FRAME == PERIOD_M30){
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_M30);
|
||||
}
|
||||
if(TIME_FRAME_TO_TRADE == PERIOD_M30)
|
||||
{
|
||||
|
||||
datetime currTime = TimeCurrent();
|
||||
Comment(TimeToString(currTime,TIME_MINUTES) + ": Sell Below: " + currentSupportLowerEdge + " Buy Above: "+ currentResistanceHighEdge);
|
||||
|
||||
string timeFrameStr = timeFrameToString(TIME_FRAME_TO_TRADE);
|
||||
|
||||
findAndDrawFractalsAndZones(TIME_FRAME_TO_TRADE,timeFrameStr);
|
||||
|
||||
if(candleClosedBelowSupportZone(TIME_FRAME_TO_TRADE)) // SELL CASE
|
||||
{
|
||||
handleSells();
|
||||
}
|
||||
|
||||
|
||||
if(candleClosedAboveResistanceZone(TIME_FRAME_TO_TRADE)) // BUY CASE
|
||||
{
|
||||
handleBuys();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(newCandleDetectorH1.isNewCandle())
|
||||
{
|
||||
if(APPLY_TRAIL && TRAIL_TIME_FRAME == PERIOD_D1 && trailWhenMarketOpensDaily){
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_D1);
|
||||
trailWhenMarketOpensDaily = false ;
|
||||
}
|
||||
if(APPLY_TRAIL && (TRAIL_TIME_FRAME == PERIOD_H1)){
|
||||
Print("Entered the trail !");
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_H1);
|
||||
}
|
||||
if(TIME_FRAME_TO_TRADE == PERIOD_H1)
|
||||
{
|
||||
datetime currTime = TimeCurrent();
|
||||
Comment(TimeToString(currTime,TIME_MINUTES) + ": Sell Below: " + currentSupportLowerEdge + " Buy Above: "+ currentResistanceHighEdge);
|
||||
|
||||
string timeFrameStr = timeFrameToString(TIME_FRAME_TO_TRADE);
|
||||
|
||||
findAndDrawFractalsAndZones(TIME_FRAME_TO_TRADE,timeFrameStr);
|
||||
|
||||
if(candleClosedBelowSupportZone(TIME_FRAME_TO_TRADE)) // SELL CASE
|
||||
{
|
||||
handleSells();
|
||||
}
|
||||
|
||||
|
||||
if(candleClosedAboveResistanceZone(TIME_FRAME_TO_TRADE)) // BUY CASE
|
||||
{
|
||||
handleBuys();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(newCandleDetectorH4.isNewCandle())
|
||||
{
|
||||
if(APPLY_TRAIL && TRAIL_TIME_FRAME == PERIOD_H4){
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_H4);
|
||||
}
|
||||
if(TIME_FRAME_TO_TRADE == PERIOD_H4)
|
||||
{
|
||||
|
||||
datetime currTime = TimeCurrent();
|
||||
Comment(TimeToString(currTime,TIME_MINUTES) + ": Sell Below: " + currentSupportLowerEdge + " Buy Above: "+ currentResistanceHighEdge);
|
||||
|
||||
string timeFrameStr = timeFrameToString(TIME_FRAME_TO_TRADE);
|
||||
|
||||
findAndDrawFractalsAndZones(TIME_FRAME_TO_TRADE,timeFrameStr);
|
||||
|
||||
if(candleClosedBelowSupportZone(TIME_FRAME_TO_TRADE)) // SELL CASE
|
||||
{
|
||||
handleSells();
|
||||
}
|
||||
|
||||
|
||||
if(candleClosedAboveResistanceZone(TIME_FRAME_TO_TRADE)) // BUY CASE
|
||||
{
|
||||
handleBuys();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(newCandleDetectorDaily.isNewCandle())
|
||||
{
|
||||
if(APPLY_TRAIL && TRAIL_TIME_FRAME == PERIOD_D1){
|
||||
trailWhenMarketOpensDaily = true ;
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_D1);
|
||||
}
|
||||
objectsManager.drawVerticalLine(clrAqua, TimeCurrent());
|
||||
}
|
||||
|
||||
if(newCandleDetectorWeekly.isNewCandle())
|
||||
{
|
||||
if(APPLY_TRAIL && TRAIL_TIME_FRAME == PERIOD_W1){
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_W1);
|
||||
}
|
||||
objectsManager.drawVerticalLine(clrRed, TimeCurrent());;
|
||||
}
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void handleSells()
|
||||
{
|
||||
|
||||
datetime currTime = TimeCurrent();
|
||||
|
||||
Comment(TimeToString(currTime,TIME_MINUTES) + ": im taking a sell !");
|
||||
|
||||
if(((indexToNewTrade = findAvailableSpotInSellManagerArr()) != -1))
|
||||
{
|
||||
|
||||
double stopLossPrice = calculateStopLossBasedOnFractalsSells(stopLossFractalsPeriod,stopLossTimeFrame) ;
|
||||
stopLossPrice = stopLossPrice + stopLossAboveWickByActual ;
|
||||
|
||||
if(stopLossIsValidSells(stopLossPrice,maxPipsRiskAmountActual))
|
||||
{
|
||||
if(rrFactor != -1 && lotSize == -1) // tp based rr metehod
|
||||
{
|
||||
if(SELLS_ALLOWED){
|
||||
double stopLossInPips = stopLossPrice - SymbolInfoDouble(_Symbol,SYMBOL_BID) ;
|
||||
double netTp = rrFactor * stopLossInPips ;
|
||||
double lotsToTrade = lsCalc.calculateLotSize(riskDollars,stopLossPrice);
|
||||
activeTradeId = sellEntryManager.takeSellTradeTiger(lotsToTrade,stopLossPrice,SymbolInfoDouble(_Symbol,SYMBOL_BID)- netTp) ;
|
||||
|
||||
SellTradeManagerTiger* tempTigerManagerSell= new SellTradeManagerTiger(activeTradeId); // create an object of type sellTradeManagerTiger
|
||||
|
||||
tempTigerManagerSell.setBrokenSupportHigherEdge(currentSupportHighEdge);
|
||||
tempTigerManagerSell.setBrokenSupportLowerEdge(currentSupportLowerEdge);
|
||||
SellActiveTradesArray[indexToNewTrade] = tempTigerManagerSell ;// put the new object in the array
|
||||
|
||||
sellsCount++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
if(rrFactor == -1 && lotSize == -1) // tp based net take profit method
|
||||
{
|
||||
if(SELLS_ALLOWED){
|
||||
double lotsToTrade = lsCalc.calculateLotSize(riskDollars,stopLossPrice);
|
||||
activeTradeId = sellEntryManager.takeSellTradeTiger(lotsToTrade,stopLossPrice,SymbolInfoDouble(_Symbol,SYMBOL_BID)- netTakeProfit) ;
|
||||
|
||||
SellTradeManagerTiger* tempTigerManagerSell= new SellTradeManagerTiger(activeTradeId); // create an object of type sellTradeManagerTiger
|
||||
|
||||
tempTigerManagerSell.setBrokenSupportHigherEdge(currentSupportHighEdge);
|
||||
tempTigerManagerSell.setBrokenSupportLowerEdge(currentSupportLowerEdge);
|
||||
SellActiveTradesArray[indexToNewTrade] = tempTigerManagerSell ;// put the new object in the array
|
||||
|
||||
sellsCount++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if(lotSize != -1){ // taking an entry based on fixed lot , and managing risk via trail
|
||||
if(SELLS_ALLOWED){
|
||||
activeTradeId = sellEntryManager.takeSellTradeTiger(lotSize,stopLossPrice) ;
|
||||
SellTradeManagerTiger* tempTigerManagerSell= new SellTradeManagerTiger(activeTradeId); // create an object of type sellTradeManagerTiger
|
||||
tempTigerManagerSell.setBrokenSupportHigherEdge(currentSupportHighEdge);
|
||||
tempTigerManagerSell.setBrokenSupportLowerEdge(currentSupportLowerEdge);
|
||||
SellActiveTradesArray[indexToNewTrade] = tempTigerManagerSell ;// put the new object in the array
|
||||
|
||||
sellsCount++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("stop loss is not valid sells!");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Comment("i cant take a trade because the arrray is full");
|
||||
}
|
||||
|
||||
currentSupportLowerEdge = -1;
|
||||
currentSupportHighEdge = -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void handleBuys()
|
||||
{
|
||||
|
||||
datetime currTime = TimeCurrent();
|
||||
Comment(TimeToString(currTime,TIME_MINUTES) + ": im taking a buy !");
|
||||
|
||||
|
||||
|
||||
if(((indexToNewTrade = findAvailableSpotInBuyManagerArr()) != -1))
|
||||
{
|
||||
|
||||
Print("indexToNewTrade:-------------------------------------------- " + indexToNewTrade);
|
||||
|
||||
double stopLossPrice = calculateStopLossBasedOnFractalsBuys(stopLossFractalsPeriod,stopLossTimeFrame);
|
||||
stopLossPrice = stopLossPrice - stopLossUnderWickByActual ;
|
||||
|
||||
if(stopLossIsValidBuys(stopLossPrice,maxPipsRiskAmountActual))
|
||||
{
|
||||
|
||||
if(rrFactor != -1 && lotSize == -1)
|
||||
{
|
||||
if(BUYS_ALLOWED){
|
||||
double stopLossInPips = SymbolInfoDouble(_Symbol,SYMBOL_ASK) - stopLossPrice ;
|
||||
double netTp = rrFactor * stopLossInPips ;
|
||||
double lotsToTrade = lsCalc.calculateLotSize(riskDollars,stopLossPrice);
|
||||
activeTradeId = buyEntryManager.takeBuyTradeTiger(lotsToTrade,stopLossPrice,SymbolInfoDouble(_Symbol,SYMBOL_ASK)+ netTp) ;
|
||||
|
||||
BuyTradeManagerTiger* tempTigerManagerBuy= new BuyTradeManagerTiger(activeTradeId); // create an object of type sellTradeManagerTiger
|
||||
tempTigerManagerBuy.setBrokenResistanceHigherEdge(currentResistanceHighEdge);
|
||||
tempTigerManagerBuy.setBrokenResistancetLowerEdge(currentResistanceLowEdge);
|
||||
BuyActiveTradesArray[indexToNewTrade] = tempTigerManagerBuy ;// put the new object in the array
|
||||
buysCount++;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
if(rrFactor == -1 && lotSize == -1)
|
||||
{
|
||||
if(BUYS_ALLOWED){
|
||||
double lotsToTrade = lsCalc.calculateLotSize(riskDollars,stopLossPrice);
|
||||
activeTradeId = buyEntryManager.takeBuyTradeTiger(lotsToTrade,stopLossPrice,SymbolInfoDouble(_Symbol,SYMBOL_ASK)+ netTakeProfit) ;
|
||||
|
||||
BuyTradeManagerTiger* tempTigerManagerBuy= new BuyTradeManagerTiger(activeTradeId); // create an object of type sellTradeManagerTiger
|
||||
tempTigerManagerBuy.setBrokenResistanceHigherEdge(currentResistanceHighEdge);
|
||||
tempTigerManagerBuy.setBrokenResistancetLowerEdge(currentResistanceLowEdge);
|
||||
BuyActiveTradesArray[indexToNewTrade] = tempTigerManagerBuy ;// put the new object in the array
|
||||
buysCount++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if(lotSize != -1){ // taking an entry based on fixed lot , and managing risk via trail
|
||||
|
||||
if(BUYS_ALLOWED){
|
||||
activeTradeId = buyEntryManager.takeBuyTradeTiger(lotSize,stopLossPrice) ;
|
||||
|
||||
BuyTradeManagerTiger* tempTigerManagerBuy= new BuyTradeManagerTiger(activeTradeId); // create an object of type sellTradeManagerTiger
|
||||
tempTigerManagerBuy.setBrokenResistanceHigherEdge(currentResistanceHighEdge);
|
||||
tempTigerManagerBuy.setBrokenResistancetLowerEdge(currentResistanceLowEdge);
|
||||
BuyActiveTradesArray[indexToNewTrade] = tempTigerManagerBuy ;// put the new object in the array
|
||||
buysCount++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("stop loss is not valid buys !");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Comment("i cant take a trade because the arrray is full");
|
||||
}
|
||||
|
||||
currentResistanceHighEdge = -1;
|
||||
currentResistanceLowEdge = -1;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,113 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BuyEntryManager.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include "BuyRejectionDetector.mqh"
|
||||
#include <Trade/Trade.mqh>
|
||||
|
||||
CTrade tradeLong ;
|
||||
class BuyEntryManager
|
||||
{
|
||||
private:
|
||||
|
||||
bool longTradeTaken ;
|
||||
bool waitingForRejectionCandle;
|
||||
bool waitingForRetracement ;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
BuyEntryManager();
|
||||
~BuyEntryManager();
|
||||
|
||||
BuyRejectionDetector* buyRejectionDetector ;
|
||||
|
||||
bool isWaitingForRejectionCandle(){return waitingForRejectionCandle ;}
|
||||
void setWaitingForRejectionCandle(bool _setting){waitingForRejectionCandle = _setting ;}
|
||||
|
||||
bool isWaitingForRetracement(){return waitingForRetracement;}
|
||||
void setWaitingForRetracement(bool _setting){waitingForRetracement = _setting ;}
|
||||
|
||||
bool buyTradeTaken();
|
||||
void setTradeTakenStatus(bool _status){longTradeTaken = _status ; Print("long trade taken flag has been set to true");}
|
||||
|
||||
|
||||
ulong takeBuyTrade(double _lots,double _stopLoss);
|
||||
ulong takeBuyTradeTiger(double _lots,double _stopLoss,double _takeProfit);
|
||||
ulong takeBuyTradeTiger(double _lots,double _stopLoss);
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyEntryManager::BuyEntryManager()
|
||||
{
|
||||
buyRejectionDetector = new BuyRejectionDetector();
|
||||
longTradeTaken = false ;
|
||||
waitingForRejectionCandle = false ;
|
||||
waitingForRetracement = false ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyEntryManager::~BuyEntryManager()
|
||||
{
|
||||
delete buyRejectionDetector ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
bool BuyEntryManager:: buyTradeTaken(){
|
||||
|
||||
|
||||
return longTradeTaken ;
|
||||
}
|
||||
|
||||
|
||||
ulong BuyEntryManager:: takeBuyTrade(double _lots, double _stopLoss){
|
||||
|
||||
tradeLong.Buy(NormalizeDouble(_lots,2),_Symbol,SymbolInfoDouble(_Symbol, SYMBOL_ASK),_stopLoss);
|
||||
|
||||
ulong tradeTicket = tradeLong.ResultOrder();
|
||||
|
||||
Print("Buy entry manager has taken a trade, ticket: " + tradeTicket);
|
||||
return tradeTicket;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
ulong BuyEntryManager:: takeBuyTradeTiger(double _lots,double _stopLoss, double _takeProft){ // first version, take the buy with fixed tp
|
||||
|
||||
double netTp = _takeProft - SymbolInfoDouble(_Symbol, SYMBOL_ASK) ;
|
||||
|
||||
tradeLong.Buy(NormalizeDouble(_lots,2),_Symbol,SymbolInfoDouble(_Symbol, SYMBOL_ASK),_stopLoss,SymbolInfoDouble(_Symbol, SYMBOL_ASK) + netTp);
|
||||
|
||||
ulong tradeTicket = tradeLong.ResultOrder();
|
||||
|
||||
Print("Buy entry manager has taken a trade, ticket: " + tradeTicket);
|
||||
return tradeTicket;
|
||||
|
||||
}
|
||||
|
||||
|
||||
ulong BuyEntryManager:: takeBuyTradeTiger(double _lots,double _stopLoss){ // second version, take the buy without a fixed tp
|
||||
|
||||
|
||||
tradeLong.Buy(NormalizeDouble(_lots,2),_Symbol,SymbolInfoDouble(_Symbol, SYMBOL_ASK),_stopLoss);
|
||||
|
||||
ulong tradeTicket = tradeLong.ResultOrder();
|
||||
|
||||
Print("Buy entry manager has taken a trade, ticket: " + tradeTicket);
|
||||
return tradeTicket;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BuyGandalf.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade/Trade.mqh>
|
||||
|
||||
CTrade tradeLong ;
|
||||
class BuyGandalf
|
||||
{
|
||||
private:
|
||||
|
||||
bool longTradeTaken ;
|
||||
ulong longTrades[10] ;
|
||||
|
||||
|
||||
public:
|
||||
BuyGandalf();
|
||||
~BuyGandalf();
|
||||
|
||||
|
||||
|
||||
bool buyTradeTaken();
|
||||
void setTradeTakenStatus(bool _status){longTradeTaken = _status ; Print("long trade taken flag has been set to true");}
|
||||
|
||||
|
||||
ulong takeBuyTrade(double _lots,double _stopLoss);
|
||||
ulong takeBuyTradeGandalf(double _lots,double _stopLoss);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyGandalf::BuyGandalf()
|
||||
{
|
||||
|
||||
longTradeTaken = false ;
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyGandalf::~BuyGandalf()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
bool BuyGandalf:: buyTradeTaken(){
|
||||
|
||||
|
||||
return longTradeTaken ;
|
||||
}
|
||||
|
||||
|
||||
ulong BuyGandalf:: takeBuyTrade(double _lots, double _stopLoss){
|
||||
|
||||
tradeLong.Buy(NormalizeDouble(_lots,2),_Symbol,SymbolInfoDouble(_Symbol, SYMBOL_ASK),_stopLoss);
|
||||
|
||||
ulong tradeTicket = tradeLong.ResultOrder();
|
||||
|
||||
Print("Buy entry manager has taken a trade, ticket: " + tradeTicket);
|
||||
return tradeTicket;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
ulong BuyGandalf:: takeBuyTradeGandalf(double _lots,double _stopLoss){
|
||||
|
||||
tradeLong.Buy(NormalizeDouble(_lots,2),_Symbol,SymbolInfoDouble(_Symbol, SYMBOL_ASK),_stopLoss);
|
||||
|
||||
ulong tradeTicket = tradeLong.ResultOrder();
|
||||
|
||||
Print("Buy entry manager has taken a trade, ticket: " + tradeTicket);
|
||||
return tradeTicket;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BuyRejectionDetector.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
class BuyRejectionDetector
|
||||
{
|
||||
private:
|
||||
|
||||
public:
|
||||
BuyRejectionDetector();
|
||||
~BuyRejectionDetector();
|
||||
|
||||
bool rejectionByOneCandleFormed(ENUM_TIMEFRAMES _timeFrame);
|
||||
bool rejectionByRangeFormed();
|
||||
bool rejectionByWicksFormed();
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyRejectionDetector::BuyRejectionDetector()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyRejectionDetector::~BuyRejectionDetector()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
bool BuyRejectionDetector:: rejectionByOneCandleFormed(ENUM_TIMEFRAMES _timeFrame){
|
||||
|
||||
double rejectionCandleClose = iClose(_Symbol,_timeFrame,1);
|
||||
double rejectionCandleOpen = iOpen(_Symbol,_timeFrame,1);
|
||||
double rejectionCandleHigh = iHigh(_Symbol,_timeFrame,1) ;
|
||||
double rejectionCandleHigherWickSize ;
|
||||
double rejectionCandleBodySize ;
|
||||
|
||||
if( rejectionCandleClose > rejectionCandleOpen ){ // the previous candle closed bullish
|
||||
rejectionCandleHigherWickSize = rejectionCandleHigh - rejectionCandleClose;
|
||||
rejectionCandleBodySize = rejectionCandleClose - rejectionCandleOpen;
|
||||
if(rejectionCandleBodySize >= rejectionCandleHigherWickSize){
|
||||
return true ;
|
||||
}
|
||||
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
@@ -0,0 +1,587 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BuyTradeManager.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#include <TradeManagersAttributes.mqh>
|
||||
#include <Telegram_Handler.mqh>
|
||||
#include <Trade/Trade.mqh>
|
||||
CTrade tradeLongInTradeManager;
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
class BuyTradeManager
|
||||
{
|
||||
private:
|
||||
int tradeId;
|
||||
ulong rejectionByOneCandleTradeArray[3];
|
||||
|
||||
string firstSecureMethod ;
|
||||
bool firstSecureMethodFound;
|
||||
int numberOfTakeProfits ;
|
||||
bool securedFirstLevelProfit ;
|
||||
bool securedSecondLevelProfit;
|
||||
double partialToClose ;
|
||||
bool isTradeRunning ;
|
||||
|
||||
|
||||
public:
|
||||
BuyTradeManager();
|
||||
~BuyTradeManager();
|
||||
|
||||
void fillRejectionByOneCandleTradeArray(int _index, int _id) {rejectionByOneCandleTradeArray[_index] = _id ;}
|
||||
ulong getRejectionByOneCandleTradeTicket(int _index) {return rejectionByOneCandleTradeArray[_index] ;}
|
||||
void printRejectionByOneCandleTradeArray();
|
||||
|
||||
void checkAndSecureTradeIfNeeded(double _ratio, double _riskInDollars);
|
||||
string findFirstSecureMethod();
|
||||
|
||||
bool reachedProfitRatio(int _indexInArr);
|
||||
bool closeTrade(int _indexInArr);
|
||||
bool positionBreakEven(int _indexInArr);
|
||||
|
||||
|
||||
void addTpAtIndex(int _index, double tpPrice) {tpArray[_index] = tpPrice;}
|
||||
int countRemainingTakeProfits();
|
||||
bool reachedClosestTakeProfit();
|
||||
void deleteClosestTp();
|
||||
int findClosestTpIndex();
|
||||
|
||||
|
||||
void cleanOrderDataStructures();
|
||||
|
||||
void setTradeRunning(bool _setting) {isTradeRunning = _setting ;}
|
||||
bool tradeIsRunning() {return isTradeRunning ;}
|
||||
|
||||
double tpArray[3];
|
||||
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyTradeManager::BuyTradeManager()
|
||||
{
|
||||
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
tpArray[i] = -1;
|
||||
}
|
||||
securedFirstLevelProfit = false ;
|
||||
securedSecondLevelProfit = false ;
|
||||
firstSecureMethodFound = false ;
|
||||
firstSecureMethod = "NOT_FOUND" ;
|
||||
partialToClose = -1 ;
|
||||
isTradeRunning = false ;
|
||||
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyTradeManager::~BuyTradeManager()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void BuyTradeManager:: printRejectionByOneCandleTradeArray()
|
||||
{
|
||||
|
||||
Print("Printing the tickets :");
|
||||
for(int i=0 ; i<3 ; i++)
|
||||
{
|
||||
Print((int)rejectionByOneCandleTradeArray[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void BuyTradeManager:: checkAndSecureTradeIfNeeded(double _ratio, double _riskInDollars)
|
||||
{
|
||||
if(securedFirstLevelProfit == false) // in this case im searching for 2 cases: either RR 1:1.5 , OR reaching the first TP , if any of them happened im gonna close half the order and updatae the remaining stop losses
|
||||
{
|
||||
|
||||
|
||||
if(!firstSecureMethodFound)
|
||||
{
|
||||
|
||||
firstSecureMethod = findFirstSecureMethod();
|
||||
if(firstSecureMethod != "FAILED")
|
||||
{
|
||||
|
||||
firstSecureMethodFound = true ;
|
||||
}
|
||||
else
|
||||
if(firstSecureMethod == "FAILED")
|
||||
{
|
||||
Print("Failed to find the first secure method, go check the function : findFirstSecureMehod() !");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(firstSecureMethodFound == true)
|
||||
{
|
||||
|
||||
if(firstSecureMethod == "RATIO_METHOD")
|
||||
{
|
||||
cleanOrderDataStructures(); // this is used each time before we are choosing an order by ticket
|
||||
if(reachedProfitRatio(0))
|
||||
{
|
||||
ChartRedraw(); // Make sure the chart is up to date
|
||||
|
||||
if(closeTrade(0)) // close the half
|
||||
{
|
||||
|
||||
rejectionByOneCandleTradeArray[0] = -1;
|
||||
Print("Closed Half Of the position due to reaching the first secure Ratio!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed Closing Half of the order by reaching the first secure Ratio !");
|
||||
}
|
||||
|
||||
cleanOrderDataStructures(); // this is used each time before we are choosing an order by ticket
|
||||
if(positionBreakEven(1)) // put the first quarter at break even
|
||||
{
|
||||
|
||||
Print(" First quarter has been put into break even due to reaching the first secure Ratio!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to Put the first quarter into break even");
|
||||
}
|
||||
|
||||
numberOfTakeProfits = countRemainingTakeProfits();
|
||||
|
||||
Print("Number of remaining tps is: " + numberOfTakeProfits);
|
||||
|
||||
securedFirstLevelProfit = true ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
if(firstSecureMethod == "FIRST_TP_METHOD")
|
||||
{
|
||||
if(countRemainingTakeProfits() > 1) // there is at least 2 tp in the tp Array (because if this is the last tp then we want to close the whole order and not just a part of it)
|
||||
{
|
||||
if(reachedClosestTakeProfit()) // 2. Check if reached the first Tp
|
||||
{
|
||||
ChartRedraw(); // Make sure the chart is up to date
|
||||
ChartScreenShot(0, fileName, 1024, 768, ALIGN_RIGHT);
|
||||
|
||||
// close the first half and update remaining partials sl's and delete the closest take profit from the array
|
||||
cleanOrderDataStructures(); // this is used each time before we are choosing an order by ticket
|
||||
if(closeTrade(0)) // close the half
|
||||
{
|
||||
|
||||
rejectionByOneCandleTradeArray[0] = -1;
|
||||
Print("Closed Half Of the position due to reaching the first TP!");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed Closing Half of the order by reaching the first TP !");
|
||||
}
|
||||
cleanOrderDataStructures(); // this is used each time before we are choosing an order by ticket
|
||||
if(positionBreakEven(1)) // put the first quarter at break even
|
||||
{
|
||||
|
||||
Print(" First quarter has been put into break even due to reaching the first TP!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to Put the first quarter into break even");
|
||||
}
|
||||
deleteClosestTp();
|
||||
numberOfTakeProfits = countRemainingTakeProfits(); // update the number of remaining take profits
|
||||
// calculate the remaining tps
|
||||
|
||||
Print("Number of remaining tps is: " + numberOfTakeProfits);
|
||||
Print("TP ARRY: " + tpArray[0] + ", " + tpArray[1] + " , " + tpArray[2]);
|
||||
|
||||
securedFirstLevelProfit = true ;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
if(numberOfTakeProfits = countRemainingTakeProfits() == 1)
|
||||
{
|
||||
if(reachedClosestTakeProfit())
|
||||
{
|
||||
// close everything remained
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
if(securedFirstLevelProfit == true) // after securing the first level i just want to close the remaining partials by reaching the tp's
|
||||
{
|
||||
|
||||
if(countRemainingTakeProfits() == 1)
|
||||
{
|
||||
if(reachedClosestTakeProfit())
|
||||
{
|
||||
// close everything
|
||||
cleanOrderDataStructures();
|
||||
for(int i=0 ; i<3 ; i++)
|
||||
{
|
||||
closeTrade(i);
|
||||
}
|
||||
Print("Closed every thing because price reached the last Take Profit !");
|
||||
|
||||
ChartRedraw(); // Make sure the chart is up to date
|
||||
|
||||
|
||||
deleteClosestTp();
|
||||
}
|
||||
}
|
||||
else
|
||||
if(countRemainingTakeProfits() > 1)
|
||||
{
|
||||
if(reachedClosestTakeProfit())
|
||||
{
|
||||
cleanOrderDataStructures();
|
||||
if(PositionSelectByTicket(rejectionByOneCandleTradeArray[1])) // DEALING WITH THE FIRST QUARTER
|
||||
{
|
||||
double currentLot = PositionGetDouble(POSITION_VOLUME);
|
||||
if(partialToClose == -1)
|
||||
{
|
||||
partialToClose = currentLot/numberOfTakeProfits ;
|
||||
}
|
||||
if(tradeLongInTradeManager.PositionClosePartial(rejectionByOneCandleTradeArray[1],NormalizeDouble(partialToClose,2)))
|
||||
{
|
||||
uint res = tradeLongInTradeManager.ResultRetcode();
|
||||
if(res == 10009)
|
||||
{
|
||||
Print("Closed Partials successfully on the first quarter !");
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("The returned code is: " + res + " go check what it means !");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to select position by ticket! , Error: " + GetLastError());
|
||||
Print("The EA tried to close partials on the first quarter, but it is closed, probably due to break even and thats why it couldnt select the order !");
|
||||
}
|
||||
|
||||
|
||||
cleanOrderDataStructures();
|
||||
if(PositionSelectByTicket(rejectionByOneCandleTradeArray[2])) // DEALING WITH THE SECOND QUARTER
|
||||
{
|
||||
if(PositionGetDouble(POSITION_SL) < PositionGetDouble(POSITION_PRICE_OPEN)) // this is to put the second quarter at break even if its not already at break even
|
||||
{
|
||||
positionBreakEven(2);
|
||||
|
||||
}
|
||||
double currentLot = PositionGetDouble(POSITION_VOLUME);
|
||||
if(partialToClose == -1)
|
||||
{
|
||||
partialToClose = currentLot/numberOfTakeProfits ;
|
||||
}
|
||||
if(tradeLongInTradeManager.PositionClosePartial(rejectionByOneCandleTradeArray[2],NormalizeDouble(partialToClose,2)))
|
||||
{
|
||||
uint res = tradeLongInTradeManager.ResultRetcode();
|
||||
if(res == 10009)
|
||||
{
|
||||
Print("Closed Partials successfully on the second quarter!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("The returned code is: " + res + " go check what it means !");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
deleteClosestTp();
|
||||
Print("Number Of Remained tps is: " + countRemainingTakeProfits());
|
||||
|
||||
ChartRedraw(); // Make sure the chart is up to date
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
string BuyTradeManager:: findFirstSecureMethod()
|
||||
{
|
||||
|
||||
cleanOrderDataStructures(); // this is used each time before we are choosing an order by ticket
|
||||
if(PositionSelectByTicket(rejectionByOneCandleTradeArray[0]))
|
||||
{
|
||||
double positionStopLoss = PositionGetDouble(POSITION_SL);
|
||||
double positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
double firstTakeProfit = tpArray[findClosestTpIndex()];
|
||||
if(((firstTakeProfit-positionOpenPrice)/(positionOpenPrice-positionStopLoss) > firstSecureRatio)) // firstTp > ratio
|
||||
{
|
||||
Print("Found the first profit secure method !");
|
||||
Print("The first TP RR is: 1:" + (firstTakeProfit-positionOpenPrice)/(positionOpenPrice-positionStopLoss) + "the firstSecureRatio is: 1:" + firstSecureRatio);
|
||||
Print("The tp ratio is greater than the firstSecure so:");
|
||||
Print("The first secure method is RATIO_METHOD");
|
||||
return"RATIO_METHOD";
|
||||
}
|
||||
else
|
||||
if((firstTakeProfit-positionOpenPrice)/(positionOpenPrice-positionStopLoss)< firstSecureRatio)
|
||||
{
|
||||
Print("Found the first profit secure method !");
|
||||
Print("The first TP RR is: 1:" + (firstTakeProfit-positionOpenPrice)/(positionOpenPrice-positionStopLoss) + "the firstSecureRatio is: 1:" + firstSecureRatio);
|
||||
Print("The tp ratio is less than the firstSecure so:");
|
||||
Print("The first secure method is FIRST_TP_METHOD");
|
||||
return "FIRST_TP_METHOD" ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to select position by ticket 1, Error: " + GetLastError());
|
||||
}
|
||||
|
||||
return "FAILED" ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool BuyTradeManager:: reachedProfitRatio(int _indexInArr)
|
||||
{
|
||||
|
||||
ulong _ticket = rejectionByOneCandleTradeArray[_indexInArr];
|
||||
if(_ticket != -1)
|
||||
{
|
||||
if(PositionSelectByTicket(_ticket))
|
||||
{
|
||||
if(PositionGetDouble(POSITION_PROFIT)/(0.5*riskDollars) >= firstSecureRatio) // checking if the first half of the contract reached the ratio of first secure profit
|
||||
{
|
||||
Print("reached profit ratio !");
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to select the position by ticket 4 ,Error: " + GetLastError());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool BuyTradeManager:: closeTrade(int _indexInArr)
|
||||
{
|
||||
|
||||
|
||||
ulong _ticket = rejectionByOneCandleTradeArray[_indexInArr];
|
||||
if(_ticket != -1)
|
||||
{
|
||||
if(PositionSelectByTicket(_ticket))
|
||||
{
|
||||
|
||||
// close the first half and update remaining partials sl's
|
||||
if(tradeLongInTradeManager.PositionClose(_ticket))
|
||||
{
|
||||
return true ;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Print("Failed to close positon, Error:" + GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Print("Failed to select position by ticket , Error: "+ GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool BuyTradeManager:: positionBreakEven(int _indexInArr)
|
||||
{
|
||||
|
||||
ulong _ticket = rejectionByOneCandleTradeArray[_indexInArr];
|
||||
if(_ticket != -1)
|
||||
{
|
||||
if(PositionSelectByTicket(_ticket)) // select the first quarter
|
||||
{
|
||||
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
double positionTp = PositionGetDouble(POSITION_TP);
|
||||
double positionSl = PositionGetDouble(POSITION_SL);
|
||||
|
||||
if(tradeLongInTradeManager.PositionModify(_ticket,openPrice,positionTp))
|
||||
{
|
||||
|
||||
|
||||
return true ;
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to modify oder , ERROR: " + GetLastError());
|
||||
return false ;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to select position by ticket ");
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int BuyTradeManager:: countRemainingTakeProfits()
|
||||
{
|
||||
|
||||
int counter = 0 ;
|
||||
for(int i=0; i<3 ; i++)
|
||||
{
|
||||
if(tpArray[i] != -1)
|
||||
{
|
||||
counter++ ;
|
||||
}
|
||||
}
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void BuyTradeManager:: deleteClosestTp()
|
||||
{
|
||||
|
||||
int closestTpIndex =findClosestTpIndex();
|
||||
tpArray[closestTpIndex] = -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int BuyTradeManager:: findClosestTpIndex()
|
||||
{
|
||||
int closestTpIndex = 0;
|
||||
int closestTpValue = 1000000 ; // dummy value
|
||||
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
if(tpArray[i] != -1 && tpArray[i] < closestTpValue)
|
||||
{
|
||||
closestTpValue = tpArray[i];
|
||||
closestTpIndex = i ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return closestTpIndex ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool BuyTradeManager:: reachedClosestTakeProfit()
|
||||
{
|
||||
|
||||
|
||||
double closestTakeProfitValue = tpArray[findClosestTpIndex()];
|
||||
//Print("im in reached closest take profit function ,the current price is: " + SymbolInfoDouble(_Symbol, SYMBOL_BID) + " and the tp is: " + closestTakeProfitValue);
|
||||
if(SymbolInfoDouble(_Symbol, SYMBOL_BID) >= closestTakeProfitValue) // we are looking for the BID , because reaching a tp in a buy trade means we are selling, so we want our take profit value, to be at least as the BID price (because we want to find someone to buy it from us at this price)
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void BuyTradeManager:: cleanOrderDataStructures()
|
||||
{
|
||||
// this is to make sure, that every closed order is removed from the data strucutre !
|
||||
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
if(!PositionSelectByTicket(rejectionByOneCandleTradeArray[i]))
|
||||
{
|
||||
if(GetLastError() == 4753)
|
||||
{
|
||||
rejectionByOneCandleTradeArray[i] = -1 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BuyTradeManagerTiger.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
class BuyTradeManagerTiger
|
||||
{
|
||||
private:
|
||||
|
||||
ulong tradeId ;
|
||||
string entryType ;
|
||||
bool firstPartialSecured ;
|
||||
bool secondPartialSecured ;
|
||||
bool managedRisk ;
|
||||
bool retestWickFormed ;
|
||||
double retestWickLengthInPips ;
|
||||
|
||||
int riskManagementCandleCounter ;
|
||||
double brokenResistanceLowerEdge ;
|
||||
double brokenResistanceHigherEdge ;
|
||||
public:
|
||||
|
||||
ulong getTradeId(){return tradeId ;}
|
||||
|
||||
bool riskAlreadyManaged(){return managedRisk ;}
|
||||
void manageRisk(){managedRisk = true ;}
|
||||
|
||||
bool firstPartialIsSecured(){return firstPartialSecured ;}
|
||||
void secureFirstPartial(){firstPartialSecured = true ;}
|
||||
|
||||
void setBrokenResistancetLowerEdge(double _brokenResistanceLowerEdge){brokenResistanceLowerEdge = _brokenResistanceLowerEdge ;}
|
||||
void setBrokenResistanceHigherEdge(double _brokenResistanceHigherEdge){brokenResistanceHigherEdge = _brokenResistanceHigherEdge ;}
|
||||
|
||||
double getBrokenResistanceLowerEdge(){return brokenResistanceLowerEdge ;}
|
||||
double getBrokenResistanceHigherEdge(){return brokenResistanceHigherEdge ;}
|
||||
|
||||
void incrementRiskManagementCandleCoutner(){riskManagementCandleCounter++ ;}
|
||||
void decrementRiskManagementCandleCounter(){riskManagementCandleCounter-- ;}
|
||||
|
||||
int getRiskManagementCandleCounter(){return riskManagementCandleCounter ;}
|
||||
|
||||
void setRiskManagementCandleCounter(int count){ riskManagementCandleCounter = count ;}
|
||||
|
||||
BuyTradeManagerTiger(ulong _tradeId);
|
||||
~BuyTradeManagerTiger();
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyTradeManagerTiger::BuyTradeManagerTiger(ulong _tradeId)
|
||||
{
|
||||
|
||||
tradeId = _tradeId ;
|
||||
firstPartialSecured = false ;
|
||||
secondPartialSecured = false ;
|
||||
managedRisk = false ;
|
||||
retestWickFormed = false ;
|
||||
retestWickLengthInPips = 0 ;
|
||||
|
||||
riskManagementCandleCounter = 0 ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyTradeManagerTiger::~BuyTradeManagerTiger()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,333 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| TigerObserver.mq5 |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
|
||||
#include "Algo_Skeleton_Functions.mqh"
|
||||
|
||||
long H4_SUPPORT_ZONE_CLR ;
|
||||
long H4_RESISTANCE_ZONE_CLR ;
|
||||
long H1_SUPPORT_ZONE_CLR;
|
||||
long H1_RESISTANCE_ZONE_CLR;
|
||||
long M30_SUPPORT_ZONE_CLR ;
|
||||
long M30_RESISTANCE_ZONE_CLR ;
|
||||
|
||||
int OnInit()
|
||||
{
|
||||
//--- create timer
|
||||
EventSetTimer(60);
|
||||
|
||||
// ONLY FOR VISULAZITAION ON STRATEGY TESTER
|
||||
iClose(_Symbol,PERIOD_W1,1);
|
||||
iClose(_Symbol,PERIOD_D1,1);
|
||||
iClose(_Symbol,PERIOD_H4,5);
|
||||
iClose(_Symbol,PERIOD_H1,5);
|
||||
iClose(_Symbol,PERIOD_M30,5);
|
||||
iClose(_Symbol,PERIOD_M15,5);
|
||||
|
||||
H4_SUPPORT_ZONE_CLR = clrBlack ;
|
||||
H4_RESISTANCE_ZONE_CLR = clrBlack ;
|
||||
|
||||
if(ENTRY_BASED_H1_STRUCTURE == true && ENTRY_BASED_M30_STRUCTURE == false){
|
||||
M30_SUPPORT_ZONE_CLR = clrBlack ;
|
||||
M30_RESISTANCE_ZONE_CLR = clrBlack ;
|
||||
|
||||
H1_SUPPORT_ZONE_CLR = clrAliceBlue ;
|
||||
H1_RESISTANCE_ZONE_CLR = clrDarkGray ;
|
||||
|
||||
}
|
||||
else if(ENTRY_BASED_H1_STRUCTURE == false && ENTRY_BASED_M30_STRUCTURE == true){
|
||||
M30_SUPPORT_ZONE_CLR = clrAliceBlue ;
|
||||
M30_RESISTANCE_ZONE_CLR = clrDarkGray ;
|
||||
|
||||
H1_SUPPORT_ZONE_CLR = clrBlack ;
|
||||
H1_RESISTANCE_ZONE_CLR = clrBlack ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
objectsManager.addTextTiger();
|
||||
|
||||
for(int i=0; i<NUM_MAX_ALLOWED_TRADES ; i++)
|
||||
{
|
||||
BuyActiveTradesArray[i] = NULL ;
|
||||
SellActiveTradesArray[i] = NULL ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//objectsManager.addMarketDescriptionTextTiger();
|
||||
|
||||
//---
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- destroy timer
|
||||
Print("Buys Count: " + buysCount);
|
||||
Print("Sells Count: " + sellsCount);
|
||||
EventKillTimer();
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//---
|
||||
|
||||
cleanBuyTradesArr();
|
||||
cleanSellTradesArr();
|
||||
secureProfitIfNeeded();
|
||||
|
||||
if(newCandleDetectorM15.isNewCandle())
|
||||
{
|
||||
|
||||
// UPDATING M30 ZONES
|
||||
if(zoneContainerSupport_M30.getNumberOfActiveZones()>0){
|
||||
updateNormalZonesSupport(zoneContainerSupport_M30,PERIOD_M30,"PERIOD_M30",M30_SUPPORT_ZONE_CLR,rangeDistanceBetweenZonesActual_M30,0);
|
||||
}
|
||||
|
||||
if(zoneContainer_M30.getNumberOfActiveZones()> 0){
|
||||
updateNormalZonesResistance(zoneContainer_M30,PERIOD_M30,"PERIOD_M30",M30_RESISTANCE_ZONE_CLR,rangeDistanceBetweenZonesActual_M30,0);
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
if(newCandleDetector30M.isNewCandle())
|
||||
{
|
||||
|
||||
if(trail_based_m30){
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_M30);
|
||||
}
|
||||
datetime currTime = TimeCurrent();
|
||||
ObjectSetString(0,"clockTextTiger",OBJPROP_TEXT,TimeToString(currTime,TIME_MINUTES));
|
||||
|
||||
detectAndDrawResistanceOnTimeFrame(PERIOD_M30,"PERIOD_M30",M30_RESISTANCE_ZONE_CLR,zoneContainer_M30,rangeDistanceBetweenZonesActual_M30,0);
|
||||
detectAndDrawSupportOnTimeFrame(PERIOD_M30,"PERIOD_M30",M30_SUPPORT_ZONE_CLR,zoneContainerSupport_M30,rangeDistanceBetweenZonesActual_M30,0);
|
||||
if(ENTRY_BASED_M30_STRUCTURE){
|
||||
|
||||
handleBuys(zoneContainer_M30,PERIOD_M30,"PERIOD_M30",cleanRangeUponEntryActual);
|
||||
handleSells(zoneContainerSupport_M30,PERIOD_M30,"PERIOD_M30",cleanRangeUponEntryActual);
|
||||
}
|
||||
else{
|
||||
|
||||
handleBullishBreakouts(zoneContainer_M30,PERIOD_M30,"PERIOD_M30");
|
||||
handleBearishBreakouts(zoneContainerSupport_M30,PERIOD_M30,"PERIOD_M30");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// UPDATING H1 ZONES
|
||||
if(zoneContainerSupport_H1.getNumberOfActiveZones()>0){
|
||||
updateNormalZonesSupport(zoneContainerSupport_H1,PERIOD_H1,"PERIOD_H1",H1_SUPPORT_ZONE_CLR,rangeDistanceBetweenZonesActual_H1,1000);
|
||||
}
|
||||
|
||||
if(zoneContainer_H1.getNumberOfActiveZones()> 0){
|
||||
updateNormalZonesResistance(zoneContainer_H1,PERIOD_H1,"PERIOD_H1",H1_RESISTANCE_ZONE_CLR,rangeDistanceBetweenZonesActual_H1,1000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
zoneContainerSupport_M30.printZonesSortedArray();
|
||||
zoneContainer_M30.printZonesSortedArray();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
if(newCandleDetector1H.isNewCandle()){
|
||||
|
||||
if(trail_based_h1){
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_H1);
|
||||
}
|
||||
|
||||
|
||||
detectAndDrawResistanceOnTimeFrame(PERIOD_H1,"PERIOD_H1",H1_RESISTANCE_ZONE_CLR,zoneContainer_H1,rangeDistanceBetweenZonesActual_H1,1000);
|
||||
detectAndDrawSupportOnTimeFrame(PERIOD_H1,"PERIOD_H1",H1_SUPPORT_ZONE_CLR,zoneContainerSupport_H1,rangeDistanceBetweenZonesActual_H1,1000);
|
||||
|
||||
if(ENTRY_BASED_H1_STRUCTURE){
|
||||
|
||||
handleBuys(zoneContainer_H1,PERIOD_H1,"PERIOD_H1",cleanRangeUponEntryActual);
|
||||
handleSells(zoneContainerSupport_H1,PERIOD_H1,"PERIOD_H1",cleanRangeUponEntryActual);
|
||||
}
|
||||
|
||||
else{
|
||||
handleBullishBreakouts(zoneContainer_H1,PERIOD_H1,"PERIOD_H1");
|
||||
handleBearishBreakouts(zoneContainerSupport_H1,PERIOD_H1,"PERIOD_H1");
|
||||
|
||||
}
|
||||
|
||||
|
||||
// UPDATING H4 ZONES
|
||||
if(zoneContainerSupport_H4.getNumberOfActiveZones()>0){
|
||||
updateNormalZonesSupport(zoneContainerSupport_H4,PERIOD_H4,"PERIOD_H4",H4_SUPPORT_ZONE_CLR,rangeDistanceBetweenZonesActual_H4,2000);
|
||||
}
|
||||
|
||||
if(zoneContainer_H4.getNumberOfActiveZones()> 0){
|
||||
updateNormalZonesResistance(zoneContainer_H4,PERIOD_H4,"PERIOD_H4",H4_RESISTANCE_ZONE_CLR,rangeDistanceBetweenZonesActual_H4,2000);
|
||||
}
|
||||
|
||||
Print("H1 zones :");
|
||||
//zoneContainerSupport_H1.printZonesSortedArray();
|
||||
//zoneContainer_H1.printZonesSortedArray();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if(newCandleDetector4H.isNewCandle()){
|
||||
last_H4_candle_broke_structure = false ;
|
||||
|
||||
if(trail_based_h4){
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_H4);
|
||||
}
|
||||
|
||||
|
||||
detectAndDrawResistanceOnTimeFrame(PERIOD_H4,"PERIOD_H4",H4_RESISTANCE_ZONE_CLR,zoneContainer_H4,rangeDistanceBetweenZonesActual_H4,2000);
|
||||
detectAndDrawSupportOnTimeFrame(PERIOD_H4,"PERIOD_H4",H4_SUPPORT_ZONE_CLR,zoneContainerSupport_H4,rangeDistanceBetweenZonesActual_H4,2000);
|
||||
|
||||
// BREAK OF STRUCTURE HANDLING
|
||||
|
||||
|
||||
handleBullishBreakouts(zoneContainer_H4,PERIOD_H4,"PERIOD_H4");
|
||||
handleBearishBreakouts(zoneContainerSupport_H4,PERIOD_H4,"PERIOD_H4");
|
||||
|
||||
//handleBuys(zoneContainer_H4,PERIOD_H4,"PERIOD_H4",cleanRangeUponEntryActual);
|
||||
//handleSells(zoneContainerSupport_H4,PERIOD_H4,"PERIOD_H4",cleanRangeUponEntryActual);
|
||||
|
||||
//Print("H4, Zones:");
|
||||
//zoneContainerSupport_H4.printZonesSortedArray();
|
||||
//zoneContainer_H4.printZonesSortedArray();
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(newCandleDetectorDaily.isNewCandle())
|
||||
{
|
||||
|
||||
//detectAndDrawResistanceOnTimeFrame(PERIOD_D1,"PERIOD_D1",clrYellow,clrYellow,zoneContainer_D1);
|
||||
//updateBreakAboveStructureAndDelete(zoneContainer_D1,PERIOD_D1,"PERIOD_D1");
|
||||
objectsManager.drawVerticalLine(clrAqua, TimeCurrent());
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
if(newCandleDetectorWeekly.isNewCandle())
|
||||
{
|
||||
|
||||
objectsManager.drawVerticalLine(clrRed, TimeCurrent());
|
||||
|
||||
weekCounter++ ;
|
||||
|
||||
if(weekCounter == deleteAllZonesAfter_Weeks){
|
||||
|
||||
//deleteAllzonesWithGUI();
|
||||
weekCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Timer function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTimer()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Trade function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTrade()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TradeTransaction function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTradeTransaction(const MqlTradeTransaction& trans,
|
||||
const MqlTradeRequest& request,
|
||||
const MqlTradeResult& result)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Tester function |
|
||||
//+------------------------------------------------------------------+
|
||||
double OnTester()
|
||||
{
|
||||
//---
|
||||
double ret=0.0;
|
||||
//---
|
||||
|
||||
//---
|
||||
return(ret);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterInit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterInit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterPass function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterPass()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterDeinit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterDeinit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnChartEvent(const int id,
|
||||
const long &lparam,
|
||||
const double &dparam,
|
||||
const string &sparam)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| BookEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnBookEvent(const string &symbol)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
|
||||
BIN
Binary file not shown.
+363
@@ -0,0 +1,363 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Gandalf.mq5 |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#include "GraphicalObjectsManager.mqh"
|
||||
#include "TempLineObjectAttributes.mqh"
|
||||
#include "ObjectConfirmationUnit.mqh"
|
||||
#include "BuyGandalf.mqh"
|
||||
#include "SellGandalf.mqh"
|
||||
#include "LotSizeCalculator.mqh"
|
||||
|
||||
|
||||
|
||||
LotSizeCalculator lsCalc;
|
||||
GraphicalObjectsManager graphicalObjectsManager ;
|
||||
ObjectConfirmationUnit objectConfUnit ;
|
||||
BuyGandalf buyGandalfGray ;
|
||||
SellGandalf SellGandalfGray ;
|
||||
|
||||
bool buyCase = false ;
|
||||
bool sellCase = false ;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
TempLineObjectAttributes tempLineObjectAttr ;
|
||||
int OnInit()
|
||||
{
|
||||
//--- create timer
|
||||
EventSetTimer(60);
|
||||
|
||||
|
||||
graphicalObjectsManager.addTotalRiskText();
|
||||
graphicalObjectsManager.addTakeBuyTradeButton();
|
||||
graphicalObjectsManager.addTakeSellTradeButton();
|
||||
graphicalObjectsManager.addText();
|
||||
graphicalObjectsManager.addConfirmButton();
|
||||
|
||||
//ObjectSetString(0,"totalRiskText",OBJPROP_TEXT,"the new ext is : !");
|
||||
|
||||
|
||||
|
||||
//---
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- destroy timer
|
||||
EventKillTimer();
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
|
||||
updateOverAllRiskText();
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Timer function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTimer()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Trade function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTrade()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TradeTransaction function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTradeTransaction(const MqlTradeTransaction& trans,
|
||||
const MqlTradeRequest& request,
|
||||
const MqlTradeResult& result)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Tester function |
|
||||
//+------------------------------------------------------------------+
|
||||
double OnTester()
|
||||
{
|
||||
//---
|
||||
double ret=0.0;
|
||||
//---
|
||||
|
||||
//---
|
||||
return(ret);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterInit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterInit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterPass function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterPass()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterDeinit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterDeinit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnChartEvent(const int id,
|
||||
const long &lparam,
|
||||
const double &dparam,
|
||||
const string &sparam)
|
||||
{
|
||||
|
||||
|
||||
|
||||
switch(id)
|
||||
{
|
||||
|
||||
case CHARTEVENT_CLICK:
|
||||
{
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//--- clicking on a graphical object
|
||||
case CHARTEVENT_OBJECT_CLICK:
|
||||
{
|
||||
|
||||
|
||||
if(sparam == "BUY_BTN")
|
||||
{
|
||||
buyCase = true ;
|
||||
|
||||
graphicalObjectsManager.drawStopLossLineGandalf();
|
||||
objectConfUnit.setWaitingStatus(true);
|
||||
|
||||
}
|
||||
|
||||
else if(sparam == "SELL_BTN"){
|
||||
sellCase = true ;
|
||||
graphicalObjectsManager.drawStopLossLineGandalf();
|
||||
objectConfUnit.setWaitingStatus(true);
|
||||
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
if(sparam == "CONFIRM_BTN")
|
||||
{
|
||||
if(buyCase == true)
|
||||
{
|
||||
if(objectConfUnit.getWaitingStatus() == true) // THIS IS TO MAKE SURE THAT THERE IS SOMETHING SELECTED TO BE CONFIRMED
|
||||
{
|
||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK) ;
|
||||
string textRecieved;
|
||||
graphicalObjectsManager.EditTextGet(textRecieved,0,"textName");
|
||||
double riskAsDouble = StringToDouble(textRecieved);
|
||||
|
||||
double stopLossPrice = tempLineObjectAttr.getPrice();
|
||||
|
||||
|
||||
|
||||
if(ObjectDelete(_Symbol,"sl"))
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to delete the stop loss line ! Error: "+ GetLastError());
|
||||
}
|
||||
|
||||
//Print("Buy info has been set, SL price: " + stopLossPrice + " risk is: " + riskAsDouble);
|
||||
|
||||
double lotsToTrade = lsCalc.calculateLotSize(riskAsDouble,stopLossPrice);
|
||||
|
||||
buyGandalfGray.takeBuyTradeGandalf(lotsToTrade,stopLossPrice);
|
||||
|
||||
objectConfUnit.setWaitingStatus(false);
|
||||
buyCase = false ;
|
||||
|
||||
// change the risk text
|
||||
//updateOverAllRiskText();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
if(sellCase == true)
|
||||
{
|
||||
|
||||
if(objectConfUnit.getWaitingStatus() == true) // THIS IS TO MAKE SURE THAT THERE IS SOMETHING SELECTED TO BE CONFIRMED
|
||||
{
|
||||
|
||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
string textRecieved;
|
||||
graphicalObjectsManager.EditTextGet(textRecieved,0,"textName");
|
||||
double riskAsDouble = StringToDouble(textRecieved);
|
||||
|
||||
double stopLossPrice = tempLineObjectAttr.getPrice();
|
||||
|
||||
if(ObjectDelete(_Symbol,"sl")){
|
||||
|
||||
|
||||
}
|
||||
else{
|
||||
|
||||
Print("Failed to delete the stop loss line ! Error: "+ GetLastError());
|
||||
}
|
||||
double lotsToTrade = lsCalc.calculateLotSize(riskAsDouble,stopLossPrice);
|
||||
SellGandalfGray.takeSellTradeGandalf(lotsToTrade,stopLossPrice);
|
||||
|
||||
objectConfUnit.setWaitingStatus(false);
|
||||
sellCase = false ;
|
||||
|
||||
|
||||
// change the risk text
|
||||
//updateOverAllRiskText();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case CHARTEVENT_OBJECT_DRAG:
|
||||
{
|
||||
|
||||
|
||||
|
||||
if(ObjectGetInteger(_Symbol,sparam,OBJPROP_TYPE,0) == OBJ_HLINE)
|
||||
{
|
||||
|
||||
if(StringSubstr(sparam,0,2) == "sl") // case of sl line (attached to a zone)
|
||||
{
|
||||
double stopLossPrice = ObjectGetDouble(_Symbol,sparam,OBJPROP_PRICE,0);
|
||||
tempLineObjectAttr.setId(sparam);
|
||||
tempLineObjectAttr.setPrice(stopLossPrice);
|
||||
}
|
||||
else
|
||||
if(StringSubstr(sparam,0,2) == "tp") // case of tp line (attached to a zone)
|
||||
{
|
||||
double takeProfitPrice = ObjectGetDouble(_Symbol,sparam,OBJPROP_PRICE,0);
|
||||
tempLineObjectAttr.setId(sparam);
|
||||
tempLineObjectAttr.setPrice(takeProfitPrice);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case CHARTEVENT_KEYDOWN:
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| BookEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnBookEvent(const string &symbol)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
void updateOverAllRiskText(){
|
||||
|
||||
|
||||
|
||||
//double pointValue = lsCalc.PointValue(_Symbol);
|
||||
|
||||
double pointValue = PointValueNew(_Symbol);
|
||||
double overAllRisk = 0 ;
|
||||
for(int i=PositionsTotal() -1 ;i >= 0 ; i--){
|
||||
//Print("entered here !");
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
int positionType = PositionGetInteger(POSITION_TYPE);
|
||||
double positionStopLossPrice = PositionGetDouble(POSITION_SL);
|
||||
double positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
double positionLotSize = PositionGetDouble(POSITION_VOLUME);
|
||||
|
||||
|
||||
if(positionType == POSITION_TYPE_BUY){
|
||||
double positionStopLossInPoints = (positionOpenPrice - positionStopLossPrice) * MathPow(10 , SymbolInfoInteger(_Symbol,SYMBOL_DIGITS)) ;
|
||||
double riskAmount = pointValue*positionLotSize*positionStopLossInPoints ;
|
||||
overAllRisk = overAllRisk + riskAmount ;
|
||||
string riskAsString = DoubleToString(overAllRisk);
|
||||
ObjectSetString(0,"totalRiskText",OBJPROP_TEXT,"Total Risk is:" + riskAsString);
|
||||
}
|
||||
else if(positionType == POSITION_TYPE_SELL){
|
||||
double positionStopLossInPoints = (positionStopLossPrice - positionOpenPrice) * MathPow(10 , SymbolInfoInteger(_Symbol,SYMBOL_DIGITS)) ;
|
||||
double riskAmount = pointValue*positionLotSize*positionStopLossInPoints ;
|
||||
overAllRisk = overAllRisk + riskAmount ;
|
||||
string riskAsString = DoubleToString(overAllRisk);
|
||||
ObjectSetString(0,"totalRiskText",OBJPROP_TEXT,"Total Risk is:" + riskAsString);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
double PointValueNew(string symbol){
|
||||
|
||||
|
||||
double tickSize = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE);
|
||||
double tickValue = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_VALUE);
|
||||
double point = SymbolInfoDouble(symbol,SYMBOL_POINT);
|
||||
double ticksPerPoint = tickSize/point ;
|
||||
double pointValue = tickValue/ticksPerPoint ;
|
||||
|
||||
return (pointValue);
|
||||
}
|
||||
Binary file not shown.
+1668
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+254
@@ -0,0 +1,254 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| HighFractal.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
class HighFractal
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
double highPrice ;
|
||||
int leftPeriod;
|
||||
int rightPeriod;
|
||||
|
||||
MqlDateTime dateStruct ;
|
||||
datetime date ;
|
||||
|
||||
double sellLimitPrice; // the fib level price , based on this fractal
|
||||
double lowestPeak ; // the highest price reached, after the fractal was formed
|
||||
int hour ;
|
||||
int minute;
|
||||
int distance ; // holds the number of candles from this fractal until the current live candle
|
||||
string arrowObjName ;
|
||||
double fibPrice ;
|
||||
|
||||
public:
|
||||
HighFractal();
|
||||
HighFractal(double _price, int _leftPeriod, int _rightPeriod, datetime _date,ENUM_TIMEFRAMES _tf);
|
||||
~HighFractal();
|
||||
|
||||
|
||||
|
||||
// GETTERS
|
||||
|
||||
double getPrice();
|
||||
int getLeftPeriod();
|
||||
int getRightPeriod();
|
||||
int getHour();
|
||||
int getMinute();
|
||||
double getLowestPeak();
|
||||
int getDistance();
|
||||
string getArrowObjName();
|
||||
datetime getDate();
|
||||
// SETTERS
|
||||
|
||||
void setPrice(double _price);
|
||||
void setLeftPeriod(int _leftPeriod);
|
||||
void setRightPeriod(int _rightPeriod);
|
||||
void setHour(int _hour);
|
||||
void setMinute(int _minute);
|
||||
void setLowestPeak(double _highest);
|
||||
void setArrowObjName(string _name);
|
||||
void setDistance(int _dist);
|
||||
void setDate(datetime _givenDate);
|
||||
|
||||
|
||||
// OTHER FUNCTIONS
|
||||
|
||||
double calculateFibPrice(double _fibLevel, double _highPrice, double _lowPrice); // calculate the fibonacci price based on the given level, and saves the price in the fibPrice88 variable in the object
|
||||
void updateDistance();
|
||||
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
HighFractal::HighFractal()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
HighFractal::HighFractal(double _price, int _leftPeriod, int _rightPeriod,datetime _date,ENUM_TIMEFRAMES _tf)
|
||||
{
|
||||
// the constructor sets the data to the attribues , and calculates the real time of the fractal , because the given minute and hour
|
||||
// are not the real time, they are the time of when the fractal was "known to be a fractal", which is after _righPeriod amount of candles
|
||||
|
||||
highPrice = _price ;
|
||||
leftPeriod = _leftPeriod;
|
||||
rightPeriod = _rightPeriod;
|
||||
sellLimitPrice = -1 ;
|
||||
distance = _rightPeriod+1;
|
||||
arrowObjName = " " ;
|
||||
lowestPeak = -1;
|
||||
|
||||
|
||||
date = iTime(_Symbol,_tf,_rightPeriod+1); // bring the actual date of the fractal
|
||||
TimeToStruct(date,dateStruct); // convert the actual date into a struct
|
||||
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
HighFractal::~HighFractal()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
double HighFractal:: getPrice()
|
||||
{
|
||||
|
||||
return highPrice ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int HighFractal:: getLeftPeriod()
|
||||
{
|
||||
|
||||
return leftPeriod ;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int HighFractal:: getRightPeriod()
|
||||
{
|
||||
|
||||
return rightPeriod ;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int HighFractal:: getHour()
|
||||
{
|
||||
|
||||
return dateStruct.hour ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int HighFractal:: getMinute()
|
||||
{
|
||||
return dateStruct.min ;
|
||||
}
|
||||
|
||||
|
||||
double HighFractal:: getLowestPeak(){
|
||||
|
||||
return lowestPeak ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int HighFractal:: getDistance(){
|
||||
|
||||
return distance ;
|
||||
}
|
||||
|
||||
|
||||
string HighFractal:: getArrowObjName(){
|
||||
return arrowObjName ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
datetime HighFractal:: getDate(){
|
||||
|
||||
return date ;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void HighFractal:: setPrice(double _price)
|
||||
{
|
||||
highPrice = _price ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void HighFractal:: setLeftPeriod(int _leftPeriod)
|
||||
{
|
||||
leftPeriod = _leftPeriod ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void HighFractal:: setRightPeriod(int _rightPeriod)
|
||||
{
|
||||
rightPeriod = _rightPeriod ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void HighFractal:: setHour(int _hour)
|
||||
{
|
||||
hour = _hour ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void HighFractal:: setMinute(int _minute)
|
||||
{
|
||||
minute = _minute ;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
void HighFractal:: setArrowObjName(string _name){
|
||||
arrowObjName = _name ;
|
||||
|
||||
}
|
||||
|
||||
void HighFractal:: setDistance(int _dist){
|
||||
distance = _dist ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double HighFractal:: calculateFibPrice(double _fibLevel, double _highPrice, double _lowPrice){
|
||||
|
||||
double difference = _lowPrice - _highPrice ;
|
||||
difference = difference*-1 ;
|
||||
double retracement = _fibLevel * difference ;
|
||||
double _fibPrice = _lowPrice + retracement ;
|
||||
fibPrice = _fibPrice ;
|
||||
return fibPrice;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void HighFractal:: setLowestPeak(double _lowest){
|
||||
|
||||
lowestPeak = _lowest ;
|
||||
|
||||
}
|
||||
|
||||
void HighFractal:: setDate(datetime _givenDate){
|
||||
date = _givenDate;
|
||||
TimeToStruct(date,dateStruct); // convert the actual date into a struct
|
||||
}
|
||||
|
||||
void HighFractal:: updateDistance(){
|
||||
|
||||
distance++ ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,131 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| HighFractalContainer.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#include "HighFractal.mqh"
|
||||
#include <library_functions.mqh>
|
||||
#define SIZE 700
|
||||
|
||||
double input arrowDistanceHighs ;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
class HighFractalContainer
|
||||
{
|
||||
private:
|
||||
HighFractal* highFractals[SIZE];
|
||||
int freeIndex ;
|
||||
double range ;
|
||||
ENUM_TIMEFRAMES timeFrame ;
|
||||
public:
|
||||
HighFractalContainer(ENUM_TIMEFRAMES _timeFrame);
|
||||
~HighFractalContainer();
|
||||
|
||||
//GETTERS
|
||||
|
||||
HighFractal* getHighFractal(int _index) {return highFractals[_index] ;} // returns the fractal using its index in the array
|
||||
int getFreeIndex() {return freeIndex ; }
|
||||
|
||||
//SETTERS
|
||||
void setRange(double _range) {range = _range ;}
|
||||
|
||||
// OTHER FUNCTIONS
|
||||
void addHighFractal(HighFractal* _highFractal); // adds high fractal to the high fractals array
|
||||
void printHighFractals(); // prints the data of every high fractal in the highFractals[] array
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
HighFractalContainer::HighFractalContainer(ENUM_TIMEFRAMES _timeFrame)
|
||||
{
|
||||
timeFrame = _timeFrame;
|
||||
freeIndex = 0 ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
HighFractalContainer::~HighFractalContainer()
|
||||
{
|
||||
|
||||
for(int i=0; i<SIZE; i++) // free the highFractals array
|
||||
{
|
||||
delete highFractals[i] ;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
void HighFractalContainer:: addHighFractal(HighFractal* _highFractal){
|
||||
|
||||
|
||||
if(freeIndex == SIZE) // in this case we are adding a new fractal but the array is full so we need to do the following
|
||||
{
|
||||
ObjectDelete(_Symbol,highFractals[0].getArrowObjName()); // delete the object arrow of the deleted fractal
|
||||
|
||||
|
||||
ObjectCreate(_Symbol,_highFractal.getArrowObjName(),OBJ_ARROW_DOWN,0,iTime(Symbol(),timeFrame,_highFractal.getDistance()),iHigh(Symbol(),timeFrame,_highFractal.getDistance()) + arrowDistanceHighs); // create the new object arrow of the new fractal
|
||||
ObjectSetInteger(0,_highFractal.getArrowObjName(),OBJPROP_COLOR,clrWhite);
|
||||
delete highFractals[0]; // free the memory allocated for the fractal in the first index (because we wanna remove it from the array)
|
||||
|
||||
|
||||
for(int i=0; i< SIZE-1 ; i++) // shift the array
|
||||
{
|
||||
|
||||
highFractals[i] = highFractals[i+1];
|
||||
}
|
||||
|
||||
highFractals[freeIndex - 1] = _highFractal ;
|
||||
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
if(freeIndex == 0) // case of the first fractal
|
||||
{
|
||||
|
||||
highFractals[freeIndex] = _highFractal ;
|
||||
freeIndex++;
|
||||
|
||||
ObjectCreate(_Symbol,_highFractal.getArrowObjName(),OBJ_ARROW_DOWN,0,iTime(Symbol(),timeFrame,_highFractal.getDistance()),iHigh(Symbol(),timeFrame,_highFractal.getDistance()) + arrowDistanceHighs);
|
||||
ObjectSetInteger(0,_highFractal.getArrowObjName(),OBJPROP_COLOR,clrWhite);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
highFractals[freeIndex] = _highFractal ;
|
||||
freeIndex++;
|
||||
ObjectCreate(_Symbol,_highFractal.getArrowObjName(),OBJ_ARROW_DOWN,0,iTime(Symbol(),timeFrame,_highFractal.getDistance()),iHigh(Symbol(),timeFrame,_highFractal.getDistance()) + arrowDistanceHighs);
|
||||
ObjectSetInteger(0,_highFractal.getArrowObjName(),OBJPROP_COLOR,clrWhite);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void HighFractalContainer:: printHighFractals()
|
||||
{
|
||||
|
||||
if(freeIndex > 0)
|
||||
{
|
||||
for(int i=0 ; i<freeIndex ; i++)
|
||||
{
|
||||
|
||||
Print(" Fractal " + i + " Time: ", highFractals[i].getHour() + ":" + highFractals[i].getMinute()+ " Price: "
|
||||
+ highFractals[i].getPrice() + " Distance: " + highFractals[i].getDistance() );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| LotSizeCalculator.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
class LotSizeCalculator
|
||||
{
|
||||
private:
|
||||
|
||||
public:
|
||||
LotSizeCalculator();
|
||||
~LotSizeCalculator();
|
||||
|
||||
double calculateLotSize(double riskInMoney,double stopLossPrice);
|
||||
|
||||
|
||||
string BaseCurrency() { return (AccountInfoString(ACCOUNT_CURRENCY)); }
|
||||
double Point(string symbol) { return (SymbolInfoDouble(symbol, SYMBOL_POINT)); }
|
||||
double TickSize(string symbol) { return (SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE)); }
|
||||
double TickValue(string symbol) { return (SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE)); }
|
||||
|
||||
double PointValue(string symbol);
|
||||
|
||||
void Test(string symbol);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
LotSizeCalculator::LotSizeCalculator()
|
||||
{
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
LotSizeCalculator::~LotSizeCalculator()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double LotSizeCalculator:: calculateLotSize(double riskInMoney, double stopLossPrice)
|
||||
{
|
||||
|
||||
double difference ;
|
||||
double differenceInPoints ;
|
||||
|
||||
if(stopLossPrice > SymbolInfoDouble(_Symbol, SYMBOL_BID)) // we are calculating for a sell
|
||||
{
|
||||
difference = stopLossPrice - SymbolInfoDouble(_Symbol, SYMBOL_BID) ;
|
||||
differenceInPoints = difference / SymbolInfoDouble(_Symbol, SYMBOL_POINT);
|
||||
double pointValue = PointValue(_Symbol);
|
||||
|
||||
// Situation 3, fixed risk amount and stop loss, how many lots to trade
|
||||
double riskInPoints = differenceInPoints;
|
||||
double riskLots = riskInMoney / (pointValue * riskInPoints);
|
||||
|
||||
return riskLots;
|
||||
}
|
||||
|
||||
if(SymbolInfoDouble(_Symbol, SYMBOL_ASK) > stopLossPrice){
|
||||
difference = SymbolInfoDouble(_Symbol, SYMBOL_ASK) - stopLossPrice ;
|
||||
differenceInPoints = difference / SymbolInfoDouble(_Symbol, SYMBOL_POINT);
|
||||
double pointValue = PointValue(_Symbol);
|
||||
double riskInPoints = differenceInPoints;
|
||||
double riskLots = riskInMoney / (pointValue * riskInPoints);
|
||||
return riskLots;
|
||||
}
|
||||
|
||||
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double LotSizeCalculator:: PointValue(string symbol)
|
||||
{
|
||||
|
||||
double tickSize = TickSize(symbol);
|
||||
double tickValue = TickValue(symbol);
|
||||
double point = Point(symbol);
|
||||
double ticksPerPoint = tickSize / point;
|
||||
double pointValue = tickValue / ticksPerPoint;
|
||||
|
||||
PrintFormat("tickSize=%f, tickValue=%f, point=%f, ticksPerPoint=%f, pointValue=%f",
|
||||
tickSize, tickValue, point, ticksPerPoint, pointValue);
|
||||
|
||||
return (pointValue);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void LotSizeCalculator:: Test(string symbol)
|
||||
{
|
||||
|
||||
PrintFormat("Base currency is %s", BaseCurrency());
|
||||
PrintFormat("Testing for symbol %s", symbol);
|
||||
|
||||
double pointValue = PointValue(symbol);
|
||||
|
||||
PrintFormat("ValuePerPoint for %s is %f", symbol, pointValue);
|
||||
|
||||
// Situation 3, fixed risk amount and stop loss, how many lots to trade
|
||||
double riskAmount = 100;
|
||||
double riskPoints = 5000;
|
||||
double riskLots = riskAmount / (pointValue * riskPoints);
|
||||
PrintFormat("Risk lots for %s value %f and stop loss at %f points is %f",
|
||||
symbol, riskAmount, riskPoints, riskLots);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
+255
@@ -0,0 +1,255 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| LowFractal.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
class LowFractal
|
||||
{
|
||||
private:
|
||||
|
||||
private:
|
||||
|
||||
double lowPrice ;
|
||||
int leftPeriod;
|
||||
int rightPeriod;
|
||||
|
||||
MqlDateTime dateStruct ;
|
||||
datetime date ;
|
||||
|
||||
double buyLimitPrice; // the fib level price , based on this fractal
|
||||
double highestPeak ; // the highest price reached, after the fractal was formed
|
||||
int hour ;
|
||||
int minute;
|
||||
int distance ; // holds the number of candles from this fractal until the current live candle
|
||||
string arrowObjName ;
|
||||
double fibPrice ;
|
||||
|
||||
public:
|
||||
LowFractal();
|
||||
LowFractal(double _price, int _leftPeriod, int _rightPeriod, datetime _date,ENUM_TIMEFRAMES _tf);
|
||||
~LowFractal();
|
||||
|
||||
|
||||
|
||||
// GETTERS
|
||||
|
||||
double getPrice();
|
||||
int getLeftPeriod();
|
||||
int getRightPeriod();
|
||||
int getHour();
|
||||
int getMinute();
|
||||
double getHighestPeak();
|
||||
int getDistance();
|
||||
string getArrowObjName();
|
||||
datetime getDate();
|
||||
// SETTERS
|
||||
|
||||
void setPrice(double _price);
|
||||
void setLeftPeriod(int _leftPeriod);
|
||||
void setRightPeriod(int _rightPeriod);
|
||||
void setHour(int _hour);
|
||||
void setMinute(int _minute);
|
||||
void setHighestPeak(double _highest);
|
||||
void setArrowObjName(string _name);
|
||||
void setDistance(int _dist);
|
||||
void setDate(datetime _givenDate);
|
||||
|
||||
|
||||
// OTHER FUNCTIONS
|
||||
|
||||
double calculateFibPrice(double _fibLevel, double _lowPrice, double _highPrice); // calculate the fibonacci price based on the given level, and saves the price in the fibPrice88 variable in the object
|
||||
void updateDistance();
|
||||
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
LowFractal::LowFractal()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
LowFractal::LowFractal(double _price, int _leftPeriod, int _rightPeriod,datetime _date, ENUM_TIMEFRAMES _tf)
|
||||
{
|
||||
// the constructor sets the data to the attribues , and calculates the real time of the fractal , because the given minute and hour
|
||||
// are not the real time, they are the time of when the fractal was "known to be a fractal", which is after _righPeriod amount of candles
|
||||
|
||||
lowPrice = _price ;
|
||||
leftPeriod = _leftPeriod;
|
||||
rightPeriod = _rightPeriod;
|
||||
buyLimitPrice = -1 ;
|
||||
distance = _rightPeriod+1;
|
||||
arrowObjName = " " ;
|
||||
highestPeak = -1;
|
||||
|
||||
|
||||
date = iTime(_Symbol,_tf,_rightPeriod+1); // bring the actual date of the fractal
|
||||
TimeToStruct(date,dateStruct); // convert the actual date into a struct
|
||||
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
LowFractal::~LowFractal()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
double LowFractal:: getPrice()
|
||||
{
|
||||
|
||||
return lowPrice ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int LowFractal:: getLeftPeriod()
|
||||
{
|
||||
|
||||
return leftPeriod ;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int LowFractal:: getRightPeriod()
|
||||
{
|
||||
|
||||
return rightPeriod ;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int LowFractal:: getHour()
|
||||
{
|
||||
|
||||
return dateStruct.hour ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int LowFractal:: getMinute()
|
||||
{
|
||||
return dateStruct.min ;
|
||||
}
|
||||
|
||||
|
||||
double LowFractal:: getHighestPeak(){
|
||||
|
||||
return highestPeak ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int LowFractal:: getDistance(){
|
||||
|
||||
return distance ;
|
||||
}
|
||||
|
||||
|
||||
string LowFractal:: getArrowObjName(){
|
||||
return arrowObjName ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
datetime LowFractal:: getDate(){
|
||||
|
||||
return date ;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void LowFractal:: setPrice(double _price)
|
||||
{
|
||||
lowPrice = _price ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void LowFractal:: setLeftPeriod(int _leftPeriod)
|
||||
{
|
||||
leftPeriod = _leftPeriod ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void LowFractal:: setRightPeriod(int _rightPeriod)
|
||||
{
|
||||
rightPeriod = _rightPeriod ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void LowFractal:: setHour(int _hour)
|
||||
{
|
||||
hour = _hour ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void LowFractal:: setMinute(int _minute)
|
||||
{
|
||||
minute = _minute ;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
void LowFractal:: setArrowObjName(string _name){
|
||||
arrowObjName = _name ;
|
||||
|
||||
}
|
||||
|
||||
void LowFractal:: setDistance(int _dist){
|
||||
distance = _dist ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double LowFractal:: calculateFibPrice(double _fibLevel, double _lowPrice, double _highPrice){
|
||||
|
||||
double difference = _highPrice - _lowPrice ;
|
||||
double retracement = _fibLevel * difference ;
|
||||
double _fibPrice = _highPrice - retracement ;
|
||||
fibPrice = _fibPrice ;
|
||||
return fibPrice;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LowFractal:: setHighestPeak(double _highest){
|
||||
|
||||
highestPeak = _highest ;
|
||||
|
||||
}
|
||||
|
||||
void LowFractal:: setDate(datetime _givenDate){
|
||||
date = _givenDate;
|
||||
TimeToStruct(date,dateStruct); // convert the actual date into a struct
|
||||
}
|
||||
|
||||
void LowFractal:: updateDistance(){
|
||||
|
||||
distance++ ;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| LowFractalContainer.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#include "LowFractal.mqh"
|
||||
#include <library_functions.mqh>
|
||||
#define SIZE 700
|
||||
|
||||
double input arrowDistanceLows ;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
class LowFractalContainer
|
||||
{
|
||||
private:
|
||||
LowFractal* lowFractals[SIZE];
|
||||
int freeIndex ;
|
||||
double range ;
|
||||
ENUM_TIMEFRAMES timeFrame ;
|
||||
public:
|
||||
LowFractalContainer(ENUM_TIMEFRAMES _timeFrame);
|
||||
~LowFractalContainer();
|
||||
|
||||
//GETTERS
|
||||
|
||||
LowFractal* getLowFractal(int _index) {return lowFractals[_index] ;} // returns the fractal using its index in the array
|
||||
int getFreeIndex() {return freeIndex ; }
|
||||
|
||||
//SETTERS
|
||||
void setRange(double _range) {range = _range ;}
|
||||
|
||||
// OTHER FUNCTIONS
|
||||
void addLowFractal(LowFractal* _lowFractal); // adds low fractal to the low fractals array
|
||||
void printLowFractals(); // prints all low fractals data
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
LowFractalContainer::LowFractalContainer(ENUM_TIMEFRAMES _timeFrame)
|
||||
{
|
||||
timeFrame = _timeFrame ;
|
||||
freeIndex = 0 ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
LowFractalContainer::~LowFractalContainer()
|
||||
{
|
||||
|
||||
for(int i=0; i<SIZE; i++) // free the lowFractals array
|
||||
{
|
||||
delete lowFractals[i] ;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
void LowFractalContainer:: addLowFractal(LowFractal* _lowFractal){
|
||||
|
||||
|
||||
if(freeIndex == SIZE) // in this case we are adding a new fractal but the array is full so we need to do the following
|
||||
{
|
||||
ObjectDelete(_Symbol,lowFractals[0].getArrowObjName()); // delete the object arrow of the deleted fractal
|
||||
|
||||
|
||||
ObjectCreate(_Symbol,_lowFractal.getArrowObjName(),OBJ_ARROW_UP,0,iTime(Symbol(),timeFrame,_lowFractal.getDistance()),iLow(Symbol(),timeFrame,_lowFractal.getDistance()) - arrowDistanceLows); // create the new object arrow of the new fractal
|
||||
ObjectSetInteger(0,_lowFractal.getArrowObjName(),OBJPROP_COLOR,clrWhite);
|
||||
delete lowFractals[0]; // free the memory allocated for the fractal in the first index (because we wanna remove it from the array)
|
||||
|
||||
|
||||
for(int i=0; i< SIZE-1 ; i++) // shift the array
|
||||
{
|
||||
|
||||
lowFractals[i] = lowFractals[i+1];
|
||||
}
|
||||
|
||||
lowFractals[freeIndex - 1] = _lowFractal ;
|
||||
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
if(freeIndex == 0) // case of the first fractal
|
||||
{
|
||||
|
||||
lowFractals[freeIndex] = _lowFractal ;
|
||||
freeIndex++;
|
||||
|
||||
ObjectCreate(_Symbol,_lowFractal.getArrowObjName(),OBJ_ARROW_UP,0,iTime(Symbol(),timeFrame,_lowFractal.getDistance()),iLow(Symbol(),timeFrame,_lowFractal.getDistance()) - arrowDistanceLows);
|
||||
ObjectSetInteger(0,_lowFractal.getArrowObjName(),OBJPROP_COLOR,clrWhite);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
lowFractals[freeIndex] = _lowFractal ;
|
||||
freeIndex++;
|
||||
ObjectCreate(_Symbol,_lowFractal.getArrowObjName(),OBJ_ARROW_UP,0,iTime(Symbol(),timeFrame,_lowFractal.getDistance()),iLow(Symbol(),timeFrame,_lowFractal.getDistance()) - arrowDistanceLows);
|
||||
ObjectSetInteger(0,_lowFractal.getArrowObjName(),OBJPROP_COLOR,clrWhite);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void LowFractalContainer:: printLowFractals()
|
||||
{
|
||||
|
||||
if(freeIndex > 0)
|
||||
{
|
||||
|
||||
for(int i=0 ; i<freeIndex ; i++)
|
||||
{
|
||||
|
||||
Print(" Fractal " + i + " Time: ", lowFractals[i].getHour() + ":" + lowFractals[i].getMinute()+ " Price: "
|
||||
+ lowFractals[i].getPrice() + " Distance: " + lowFractals[i].getDistance() );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,299 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| MarketObserver.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#include "Zone.mqh"
|
||||
#include "ZoneContainer.mqh"
|
||||
#include "LowFractal.mqh"
|
||||
#include "HighFractal.mqh"
|
||||
#include "LowFractalContainer.mqh"
|
||||
#include "HighFractalContainer.mqh"
|
||||
|
||||
|
||||
// ALGORITHM CLASSES INCLUDES
|
||||
|
||||
#include "NewCandleDetector.mqh"
|
||||
|
||||
|
||||
// LIVE FORMING FRACTALS HANDLER CLASS
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
class MarketObserver
|
||||
{
|
||||
// THIS CLASS HAS ACCESS TO ZONE CONTAINER, HOWEVER IT MUST NOT CHANGE IT IT ONLY READS FROM THE ZONECONTAINER CLASS
|
||||
private:
|
||||
/*NewCandleDetector* newCandleDetector_H4;
|
||||
NewCandleDetector* newCandleDetector_H1 ;
|
||||
NewCandleDetector* newCandleDetector_M30;
|
||||
NewCandleDetector* newCandleDetector_M1 ;*/
|
||||
ZoneContainer* zoneContainer ; // must not be changed from this class
|
||||
bool closestResistanceWaiting ;
|
||||
bool closestSupportWaiting ;
|
||||
public:
|
||||
MarketObserver(ZoneContainer* _zoneContainer);
|
||||
~MarketObserver();
|
||||
|
||||
string zoneReached();
|
||||
|
||||
Zone* getClosestResistanceZone() {return zoneContainer.getHigherPivotIndexZone();}
|
||||
Zone* getClosestSupportZone() {return zoneContainer.getLowerPivotIndexZone();}
|
||||
bool reachedClosestSupportZone();
|
||||
bool reachedClosestResistanceZone();
|
||||
|
||||
|
||||
bool bearishCandleClosedInsideClosestSupportZone(ENUM_TIMEFRAMES tf);
|
||||
bool bullishCandleClosedInsideClosestResistanceZone(ENUM_TIMEFRAMES tf);
|
||||
|
||||
bool candleClosedBelowClosestSupportZone(ENUM_TIMEFRAMES tf);
|
||||
bool candleClosedAboveClosestResistanceZone(ENUM_TIMEFRAMES tf);
|
||||
bool candleClosedAboveResistanceByIndex(int _index,ENUM_TIMEFRAMES tf); // the index is a specific zone from the zones container
|
||||
bool candleClosedBelowSupportByIndex(int _index,ENUM_TIMEFRAMES tf); // the index is a specific zone from the zones container
|
||||
|
||||
bool isClosestResistanceWaiting() {return closestResistanceWaiting;}
|
||||
bool isClosestSupportWaiting() {return closestSupportWaiting;}
|
||||
|
||||
void setClosestResistanceWaiting(bool _state) {closestResistanceWaiting = _state ;}
|
||||
void setClosestSupportWaiting(bool _state) {closestSupportWaiting = _state ;}
|
||||
|
||||
|
||||
string giveMarketReport();
|
||||
|
||||
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
MarketObserver::MarketObserver(ZoneContainer* _zoneContainer)
|
||||
{
|
||||
/*newCandleDetector_H4 = new NewCandleDetector("PERIOD_H4") ;
|
||||
newCandleDetector_H1 = new NewCandleDetector("PERIOD_H1");
|
||||
newCandleDetector_M30 = new NewCandleDetector("PERIOD_M30");
|
||||
newCandleDetector_M1 = new NewCandleDetector("PERIOD_M1");*/
|
||||
|
||||
zoneContainer = _zoneContainer ;
|
||||
closestResistanceWaiting = false ;
|
||||
closestSupportWaiting = false ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
MarketObserver::~MarketObserver()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
string MarketObserver:: zoneReached()
|
||||
{
|
||||
|
||||
|
||||
int currentResistanceZoneIndex = zoneContainer.getHighZonePivot();
|
||||
int currentSupportZoneIndex = zoneContainer.getLowZonePivot();
|
||||
|
||||
if(currentResistanceZoneIndex != -1 && currentSupportZoneIndex != -1)
|
||||
{
|
||||
|
||||
|
||||
if(SymbolInfoDouble(_Symbol, SYMBOL_ASK) >= zoneContainer.getZoneByIndex(currentResistanceZoneIndex).getLowerEdge())
|
||||
{
|
||||
|
||||
Print("Reached the current resistance zone !");
|
||||
return "TYPE_RESISTANCE" ;
|
||||
|
||||
}
|
||||
|
||||
if(SymbolInfoDouble(_Symbol, SYMBOL_ASK) <= zoneContainer.getZoneByIndex(currentSupportZoneIndex).getHigherEdge())
|
||||
{
|
||||
Print("Reached the current support zone !");
|
||||
return "TYPE_SUPPORT" ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return "" ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MarketObserver:: reachedClosestSupportZone()
|
||||
{
|
||||
|
||||
int currentSupportZoneIndex = zoneContainer.getLowZonePivot();
|
||||
|
||||
if(currentSupportZoneIndex != -1)
|
||||
{
|
||||
if(SymbolInfoDouble(_Symbol, SYMBOL_ASK) <= zoneContainer.getZoneByIndex(currentSupportZoneIndex).getHigherEdge())
|
||||
{
|
||||
return true ;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MarketObserver:: reachedClosestResistanceZone()
|
||||
{
|
||||
|
||||
int currentResistanceZoneIndex = zoneContainer.getHighZonePivot();
|
||||
|
||||
if(currentResistanceZoneIndex != -1)
|
||||
{
|
||||
|
||||
if(SymbolInfoDouble(_Symbol, SYMBOL_ASK) >= zoneContainer.getZoneByIndex(currentResistanceZoneIndex).getLowerEdge())
|
||||
{
|
||||
return true ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MarketObserver:: bullishCandleClosedInsideClosestResistanceZone(ENUM_TIMEFRAMES tf)
|
||||
{
|
||||
|
||||
double previousCandleClose = iClose(_Symbol,tf,1);
|
||||
double previousCandleOpen = iOpen(_Symbol,tf,1);
|
||||
|
||||
if(zoneContainer.getHighZonePivot() != -1) // means if there is a pivot zone
|
||||
{
|
||||
|
||||
if((previousCandleClose > previousCandleOpen) && (previousCandleClose > zoneContainer.getZoneByIndex(zoneContainer.getHighZonePivot()).getLowerEdge()) && (previousCandleClose < zoneContainer.getZoneByIndex(zoneContainer.getHighZonePivot()).getHigherEdge())) // means if previous the candle is bullish and closed inside the resistance zone
|
||||
{
|
||||
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MarketObserver:: bearishCandleClosedInsideClosestSupportZone(ENUM_TIMEFRAMES tf)
|
||||
{
|
||||
|
||||
double previousCandleClose = iClose(_Symbol,tf,1);
|
||||
double previousCandleOpen = iOpen(_Symbol,tf,1);
|
||||
|
||||
if(zoneContainer.getLowZonePivot() != -1)
|
||||
{
|
||||
if((previousCandleClose < previousCandleOpen) && (previousCandleClose < zoneContainer.getZoneByIndex(zoneContainer.getLowZonePivot()).getHigherEdge()) && (previousCandleClose > zoneContainer.getZoneByIndex(zoneContainer.getLowZonePivot()).getLowerEdge())) // means if previous the candle is breaish and closed inside the support zone
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
string MarketObserver:: giveMarketReport()
|
||||
{
|
||||
|
||||
|
||||
return " " ;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MarketObserver:: candleClosedBelowClosestSupportZone(ENUM_TIMEFRAMES tf)
|
||||
{
|
||||
|
||||
double previousCandleClose = iClose(_Symbol,tf,1);
|
||||
double previousCandleOpen = iOpen(_Symbol,tf,1);
|
||||
|
||||
|
||||
if(zoneContainer.getLowZonePivot() != -1)
|
||||
{
|
||||
if((previousCandleClose < zoneContainer.getZoneByIndex(zoneContainer.getLowZonePivot()).getLowerEdge())) // means if the previous candle closed below the support zone
|
||||
{
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MarketObserver:: candleClosedAboveClosestResistanceZone(ENUM_TIMEFRAMES tf)
|
||||
{
|
||||
|
||||
double previousCandleClose = iClose(_Symbol,tf,1);
|
||||
double previousCandleOpen = iOpen(_Symbol,tf,1);
|
||||
|
||||
if(zoneContainer.getHighZonePivot() != -1) // means if there is a pivot zone
|
||||
{
|
||||
|
||||
if((previousCandleClose > zoneContainer.getZoneByIndex(zoneContainer.getHighZonePivot()).getHigherEdge())) // means if previous the candle closed above the resistance zone
|
||||
{
|
||||
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool MarketObserver:: candleClosedAboveResistanceByIndex(int _index,ENUM_TIMEFRAMES tf){
|
||||
|
||||
double previousCandleClose = iClose(_Symbol,tf,1);
|
||||
|
||||
if((previousCandleClose > zoneContainer.getZoneByIndex(_index).getHigherEdge())){
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,105 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| MarketObserverTiger.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
//+------------------------------------------------------------------+
|
||||
//| defines |
|
||||
//+------------------------------------------------------------------+
|
||||
// #define MacrosHello "Hello, world!"
|
||||
// #define MacrosYear 2010
|
||||
//+------------------------------------------------------------------+
|
||||
//| DLL imports |
|
||||
//+------------------------------------------------------------------+
|
||||
// #import "user32.dll"
|
||||
// int SendMessageA(int hWnd,int Msg,int wParam,int lParam);
|
||||
// #import "my_expert.dll"
|
||||
// int ExpertRecalculate(int wParam,int lParam);
|
||||
// #import
|
||||
//+------------------------------------------------------------------+
|
||||
//| EX5 imports |
|
||||
//+------------------------------------------------------------------+
|
||||
// #import "stdlib.ex5"
|
||||
// string ErrorDescription(int error_code);
|
||||
// #import
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Zone.mqh"
|
||||
#include "ZoneContainer.mqh"
|
||||
|
||||
|
||||
// ALGORITHM CLASSES INCLUDES
|
||||
|
||||
#include "NewCandleDetector.mqh"
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
class MarketObserverTiger
|
||||
{
|
||||
// THIS CLASS HAS ACCESS TO ZONE CONTAINER, HOWEVER IT MUST NOT CHANGE IT IT ONLY READS FROM THE ZONECONTAINER CLASS
|
||||
private:
|
||||
|
||||
|
||||
|
||||
public:
|
||||
MarketObserverTiger();
|
||||
~MarketObserverTiger();
|
||||
|
||||
string zoneReached();
|
||||
bool candleClosedAboveResistanceByIndex(int _index,ENUM_TIMEFRAMES tf,ZoneContainer& resistanceZoneContainer); // the index is a specific zone from the zones container
|
||||
bool candleClosedBelowSupportByIndex(int _index,ENUM_TIMEFRAMES tf,ZoneContainer& supportZoneContainer); // the index is a specific zone from the zones container
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
MarketObserverTiger::MarketObserverTiger()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
MarketObserverTiger::~MarketObserverTiger()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MarketObserverTiger:: candleClosedAboveResistanceByIndex(int _index,ENUM_TIMEFRAMES tf,ZoneContainer& resistanceZoneContainer)
|
||||
{
|
||||
|
||||
double previousCandleClose = iClose(_Symbol,tf,1);
|
||||
|
||||
if((previousCandleClose > resistanceZoneContainer.getZoneByIndex(_index).getHigherEdge()))
|
||||
{
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool MarketObserverTiger:: candleClosedBelowSupportByIndex(int _index, ENUM_TIMEFRAMES tf, ZoneContainer& supportZoneContainer){
|
||||
|
||||
|
||||
double previousCandleClose = iClose(_Symbol,tf,1);
|
||||
if(previousCandleClose < supportZoneContainer.getZoneByIndex(_index).getLowerEdge()){
|
||||
return true ;
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
@@ -0,0 +1,378 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| NewCandleDetector.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
class NewCandleDetector
|
||||
{
|
||||
private:
|
||||
string timeFrame ;
|
||||
datetime beginDate ; // this datetime gets initialized only after the first call of the isNewCandle() function
|
||||
MqlDateTime currTimeStruct;
|
||||
MqlDateTime beginDateStruct;
|
||||
bool firstCallHappened;
|
||||
public:
|
||||
NewCandleDetector(string _timeFrame);
|
||||
|
||||
~NewCandleDetector();
|
||||
|
||||
// GETTERS
|
||||
datetime getBeginDate() {return beginDate;}
|
||||
|
||||
void setTimeFrame(string _timeFrame) {timeFrame = _timeFrame;}
|
||||
bool isNewCandle();
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
NewCandleDetector::NewCandleDetector(string _timeFrame)
|
||||
{
|
||||
|
||||
timeFrame = _timeFrame ;
|
||||
firstCallHappened = false;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
NewCandleDetector::~NewCandleDetector()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool NewCandleDetector:: isNewCandle()
|
||||
{
|
||||
|
||||
|
||||
|
||||
if(timeFrame == "PERIOD_M1")
|
||||
{
|
||||
|
||||
if(firstCallHappened == false)
|
||||
{
|
||||
|
||||
beginDate = iTime(_Symbol,PERIOD_M1,0);
|
||||
firstCallHappened = true;
|
||||
}
|
||||
|
||||
if(firstCallHappened == true)
|
||||
{
|
||||
datetime currTime = iTime(_Symbol,PERIOD_M1,0);
|
||||
TimeToStruct(beginDate,beginDateStruct);
|
||||
TimeToStruct(currTime,currTimeStruct);
|
||||
|
||||
if(beginDateStruct.min == currTimeStruct.min)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Print("in a new candle !, asset: " + _Symbol);
|
||||
beginDate = currTime;
|
||||
return true ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_M2")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
if(timeFrame == "PERIOD_M3")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_M4")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_M5")
|
||||
{
|
||||
|
||||
if(firstCallHappened == false)
|
||||
{
|
||||
beginDate = iTime(_Symbol,PERIOD_M5,0);
|
||||
firstCallHappened = true;
|
||||
}
|
||||
|
||||
if(firstCallHappened == true)
|
||||
{
|
||||
datetime currTime = iTime(_Symbol,PERIOD_M5,0);
|
||||
TimeToStruct(beginDate,beginDateStruct);
|
||||
TimeToStruct(currTime,currTimeStruct);
|
||||
|
||||
if(beginDateStruct.min == currTimeStruct.min)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("in a new candle !, asset: " + _Symbol);
|
||||
beginDate = currTime;
|
||||
return true ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_M6")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_M10")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_M12")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_M15")
|
||||
{
|
||||
|
||||
if(firstCallHappened == false)
|
||||
{
|
||||
beginDate = iTime(_Symbol,PERIOD_M15,0);
|
||||
firstCallHappened = true;
|
||||
}
|
||||
|
||||
if(firstCallHappened == true)
|
||||
{
|
||||
datetime currTime = iTime(_Symbol,PERIOD_M15,0);
|
||||
TimeToStruct(beginDate,beginDateStruct);
|
||||
TimeToStruct(currTime,currTimeStruct);
|
||||
|
||||
if(beginDateStruct.min == currTimeStruct.min)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
beginDate = currTime;
|
||||
return true ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_M20")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_M30")
|
||||
{
|
||||
if(firstCallHappened == false)
|
||||
{
|
||||
beginDate = iTime(_Symbol,PERIOD_M30,0);
|
||||
firstCallHappened = true;
|
||||
}
|
||||
|
||||
if(firstCallHappened == true)
|
||||
{
|
||||
datetime currTime = iTime(_Symbol,PERIOD_M30,0);
|
||||
TimeToStruct(beginDate,beginDateStruct);
|
||||
TimeToStruct(currTime,currTimeStruct);
|
||||
|
||||
if(beginDateStruct.min == currTimeStruct.min)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
beginDate = currTime;
|
||||
return true ;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_H1")
|
||||
{
|
||||
if(firstCallHappened == false)
|
||||
{
|
||||
beginDate = iTime(_Symbol,PERIOD_H1,0);
|
||||
firstCallHappened = true;
|
||||
}
|
||||
|
||||
if(firstCallHappened == true)
|
||||
{
|
||||
datetime currTime = iTime(_Symbol,PERIOD_H1,0);
|
||||
TimeToStruct(beginDate,beginDateStruct);
|
||||
TimeToStruct(currTime,currTimeStruct);
|
||||
|
||||
if(beginDateStruct.hour == currTimeStruct.hour)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
beginDate = currTime;
|
||||
return true ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_H2")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_H3")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_H4")
|
||||
{
|
||||
if(firstCallHappened == false)
|
||||
{
|
||||
beginDate = iTime(_Symbol,PERIOD_H4,0);
|
||||
firstCallHappened = true;
|
||||
}
|
||||
|
||||
if(firstCallHappened == true)
|
||||
{
|
||||
datetime currTime = iTime(_Symbol,PERIOD_H4,0);
|
||||
TimeToStruct(beginDate,beginDateStruct);
|
||||
TimeToStruct(currTime,currTimeStruct);
|
||||
|
||||
if(beginDateStruct.hour == currTimeStruct.hour)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
beginDate = currTime;
|
||||
return true ;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_H6")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_H8")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_H12")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_D1")
|
||||
{
|
||||
|
||||
if(firstCallHappened == false)
|
||||
{
|
||||
beginDate = iTime(_Symbol,PERIOD_D1,0);
|
||||
firstCallHappened = true;
|
||||
}
|
||||
|
||||
if(firstCallHappened == true)
|
||||
{
|
||||
datetime currTime = iTime(_Symbol,PERIOD_D1,0);
|
||||
TimeToStruct(beginDate,beginDateStruct);
|
||||
TimeToStruct(currTime,currTimeStruct);
|
||||
|
||||
if(beginDateStruct.day == currTimeStruct.day)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
beginDate = currTime;
|
||||
return true ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_W1")
|
||||
{
|
||||
|
||||
|
||||
if(firstCallHappened == false)
|
||||
{
|
||||
beginDate = iTime(_Symbol,PERIOD_W1,0);
|
||||
firstCallHappened = true;
|
||||
}
|
||||
|
||||
if(firstCallHappened == true)
|
||||
{
|
||||
datetime currTime = iTime(_Symbol,PERIOD_W1,0);
|
||||
TimeToStruct(beginDate,beginDateStruct);
|
||||
TimeToStruct(currTime,currTimeStruct);
|
||||
|
||||
if(beginDateStruct.day == currTimeStruct.day)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
beginDate = currTime;
|
||||
return true ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_MN1")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
+1643
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,50 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ObjectConfirmationUnit.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
/*
|
||||
This class is responsible for all the proccess of confirming a new object. it prevents adding new objects if the previous was not confirmed.
|
||||
*/
|
||||
|
||||
class ObjectConfirmationUnit
|
||||
{
|
||||
private:
|
||||
string confirmationObjectID ;
|
||||
string objectType ;
|
||||
bool waitingToBeConfirmed ;
|
||||
|
||||
|
||||
public:
|
||||
ObjectConfirmationUnit();
|
||||
~ObjectConfirmationUnit();
|
||||
|
||||
// GETTERS
|
||||
string getObjectType(){ return objectType ;}
|
||||
bool getWaitingStatus(){ return waitingToBeConfirmed ;}
|
||||
string getConfirmationObjectId(){return confirmationObjectID;}
|
||||
|
||||
// SETTERS
|
||||
void setObjectType(string _type){ objectType = _type ;}
|
||||
void setWaitingStatus(bool _waitStatus){ waitingToBeConfirmed = _waitStatus ;}
|
||||
void setConfirmationObjectId(int _Id){ confirmationObjectID = IntegerToString(_Id) ;}
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
ObjectConfirmationUnit::ObjectConfirmationUnit()
|
||||
{
|
||||
waitingToBeConfirmed = false ; // initialize with false value
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
ObjectConfirmationUnit::~ObjectConfirmationUnit()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,618 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Phoenix_Functions.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#define NUM_MAX_ALLOWED_TRADES 4
|
||||
#include "library_functions.mqh"
|
||||
#include "NewCandleDetector.mqh"
|
||||
#include "GraphicalObjectsManager.mqh"
|
||||
#include "Zone.mqh"
|
||||
#include "ZoneContainer.mqh"
|
||||
#include "LotSizeCalculator.mqh"
|
||||
#include "MarketObserverTiger.mqh"
|
||||
|
||||
#include "BuyEntryManager.mqh"
|
||||
#include "SellEntryManager.mqh"
|
||||
#include "BuyTradeManagerTiger.mqh"
|
||||
#include "SellTradeManagerTiger.mqh"
|
||||
|
||||
|
||||
//input group "Range Related Variables"
|
||||
//input double rangeDistanceBetweenZones ;
|
||||
//input double cleanRangeUponEntry ;
|
||||
//input double potentialRR;
|
||||
|
||||
input group "Zone Related Settings"
|
||||
input double resistanceExtendAboveCandle;
|
||||
input double resistanceLowerEdgeExtend ;
|
||||
input double supportExtendBelowCandle ;
|
||||
input double supportHigherEdgeExtend;
|
||||
input int firstZoneShift ;
|
||||
input datetime rightEdge ;
|
||||
|
||||
//input group "Zone TimeFrames"
|
||||
//input bool APPLY_M30_STRUCTURE ;
|
||||
//input bool APPLY_H1_STRUCTURE;
|
||||
|
||||
|
||||
|
||||
//input group "Candle Body Variables"
|
||||
//input double WICK_RATIO_REJECTION;
|
||||
//input double SIZE_OF_BREAKER_CANDLE_BODY;
|
||||
|
||||
input group "Trade Related Variables 2"
|
||||
input double riskManagementPartial ;
|
||||
input double firstPartialCloseFactor ;
|
||||
input double firstPartialProfitInPips;
|
||||
input bool BUYS_ALLOWED = true ;
|
||||
input bool SELLS_ALLOWED = true ;
|
||||
input double lotSize ;
|
||||
input int riskManagementCandlesCount ;
|
||||
input double rrFactor ;
|
||||
input bool APPLY_TRAIL ;
|
||||
input ENUM_TIMEFRAMES TRAIL_TIME_FRAME ;
|
||||
|
||||
|
||||
//input group "Trading Sessions"
|
||||
//input bool TRADE_NEW_YORK_ALLOWED = true ;
|
||||
//input bool TRADE_LONDON_ALLOWED = true ;
|
||||
|
||||
input group "Fractal Related Variables"
|
||||
//input int leftFractalPeriod ;
|
||||
//input int rightFractalPeriod ;
|
||||
input ENUM_TIMEFRAMES TIME_FRAME_TO_TRADE;
|
||||
input int fractalsPeriod ;
|
||||
input int stopLossFractalsPeriod ;
|
||||
input ENUM_TIMEFRAMES stopLossTimeFrame ;
|
||||
|
||||
// GUI CLASSES INITIALIZATION
|
||||
GraphicalObjectsManager* objectsManager = new GraphicalObjectsManager();
|
||||
|
||||
|
||||
|
||||
// ALGORITHM CLASSES INITIALIZATION
|
||||
MarketObserverTiger* marketObserverTiger = new MarketObserverTiger();
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
NewCandleDetector newCandleDetectorWeekly("PERIOD_W1");
|
||||
NewCandleDetector newCandleDetectorDaily("PERIOD_D1");
|
||||
NewCandleDetector newCandleDetectorH4("PERIOD_H4");
|
||||
NewCandleDetector newCandleDetectorH1("PERIOD_H1");
|
||||
NewCandleDetector newCandleDetectorM30("PERIOD_M30");
|
||||
NewCandleDetector newCandleDetectorM15("PERIOD_M15");
|
||||
NewCandleDetector newCandleDetectorM5("PERIOD_M5");
|
||||
NewCandleDetector newCandleDetectorM1("PERIOD_M1");
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
Zone* temporaryRestestSupportZone = new Zone();
|
||||
|
||||
|
||||
|
||||
// TRADE CLASSES
|
||||
BuyEntryManager buyEntryManager ;
|
||||
SellEntryManager sellEntryManager ;
|
||||
|
||||
|
||||
// LotSizeCalculator class
|
||||
LotSizeCalculator lsCalc ;
|
||||
|
||||
|
||||
// TRADE VARIABLS
|
||||
bool securedRisk = false ;
|
||||
ulong activeTradeId ;
|
||||
BuyTradeManagerTiger* BuyActiveTradesArray[NUM_MAX_ALLOWED_TRADES];
|
||||
SellTradeManagerTiger* SellActiveTradesArray[NUM_MAX_ALLOWED_TRADES];
|
||||
int buysCount = 0 ;
|
||||
int sellsCount = 0 ;
|
||||
bool waitForBottomWick = false ;
|
||||
bool bottomWickFormed = false;
|
||||
bool topWickFormed = false;
|
||||
bool waitForTopWick = false ;
|
||||
|
||||
|
||||
double currentResistanceHighEdge = -1 ;
|
||||
double currentResistanceLowEdge = -1 ;
|
||||
double currentSupportHighEdge = -1 ;
|
||||
double currentSupportLowerEdge = -1;
|
||||
|
||||
|
||||
double currentSupportZonePrice ;
|
||||
double currentResistanceZonePrice;
|
||||
|
||||
int indexToNewTrade ;
|
||||
|
||||
|
||||
// DATA STRUCTURES
|
||||
|
||||
double lastLowFractalPrice ;
|
||||
double lastHighFractalPrice ;
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double supportExtendBelowCandleActual = supportExtendBelowCandle * Point();
|
||||
double supportHigherEdgeExtendActual = supportHigherEdgeExtend * Point();
|
||||
double resistanceExtendAboveCandleActual = resistanceExtendAboveCandle * Point();
|
||||
double resistanceLowerEdgeExtendActual = resistanceLowerEdgeExtend * Point();
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double stopLossAboveWickByActual = stopLossAboveWickBy * Point() ;
|
||||
double stopLossUnderWickByActual = stopLossUnderWickBy * Point() ;
|
||||
|
||||
|
||||
//double cleanRangeUponEntryActual = cleanRangeUponEntry * Point() ;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
//double rangeDistanceBetweenZonesActual_H4 = rangeDistanceBetweenZones_4H * Point();
|
||||
//double rangeDistanceBetweenZonesActual_M30 = rangeDistanceBetweenZones_M30 * Point();
|
||||
|
||||
double maxPipsRiskAmountActual = maxPipsRiskAmount * Point();
|
||||
|
||||
double firstPartialProfitInPipsActual = firstPartialProfitInPips * Point();
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double detectSupportFromLastLowFractal(int _index)
|
||||
{
|
||||
double lastLowestSupportPrice = 99999;
|
||||
for(int i= _index ; i > 1 ; i--)
|
||||
{
|
||||
if((candleClosedBearish(PERIOD_CURRENT,i) && candleClosedBullish(PERIOD_CURRENT,i-1))|| (candleClosedBearish(PERIOD_CURRENT,i) && candleClosedDoji(PERIOD_CURRENT,i-1)))
|
||||
{
|
||||
if(iClose(_Symbol,PERIOD_CURRENT,i) < lastLowestSupportPrice)
|
||||
{
|
||||
lastLowestSupportPrice = iClose(_Symbol,PERIOD_CURRENT,i);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lastLowestSupportPrice ;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double detectResistanceFromLastHighFractal(int _index)
|
||||
{
|
||||
|
||||
|
||||
double lastHighestResistancePrice = -1;
|
||||
for(int i= _index ; i > 1 ; i--)
|
||||
{
|
||||
if((candleClosedBullish(PERIOD_CURRENT,i) && candleClosedBearish(PERIOD_CURRENT,i-1))|| (candleClosedBullish(PERIOD_CURRENT,i) && candleClosedDoji(PERIOD_CURRENT,i-1)))
|
||||
{
|
||||
if(iClose(_Symbol,PERIOD_CURRENT,i) > lastHighestResistancePrice)
|
||||
{
|
||||
lastHighestResistancePrice = iClose(_Symbol,PERIOD_CURRENT,i);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lastHighestResistancePrice ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void findAndDrawFractalsAndZones(ENUM_TIMEFRAMES _timeFrame, string _timeFrameStr)
|
||||
{
|
||||
if(isLowFractalByIndex(fractalsPeriod+1,fractalsPeriod,fractalsPeriod,_timeFrame)) // SUPPORTS
|
||||
{
|
||||
objectsManager.drawLowFractal(fractalsPeriod+1,clrRed);
|
||||
lastLowFractalPrice = iLow(_Symbol,PERIOD_CURRENT,fractalsPeriod+1);
|
||||
currentSupportZonePrice = detectSupportFromLastLowFractal(fractalsPeriod+5);
|
||||
|
||||
datetime _leftEdge = iTime(_Symbol,PERIOD_CURRENT,fractalsPeriod+1);
|
||||
datetime _rightEdge =rightEdge;
|
||||
double _higherEdgePrice = currentSupportZonePrice + supportHigherEdgeExtendActual;
|
||||
double _lowerEdgePrice = currentSupportZonePrice - supportExtendBelowCandleActual;
|
||||
|
||||
currentSupportLowerEdge = _lowerEdgePrice;
|
||||
currentSupportHighEdge = _higherEdgePrice ;
|
||||
|
||||
Zone* supportZoneObject = new Zone("support_zone",_higherEdgePrice,_lowerEdgePrice,_leftEdge,_rightEdge,_timeFrameStr,"TYPE_SUPPORT_BREAKOUT");
|
||||
objectsManager.drawRectangleInStrategyTester(1,_leftEdge,_rightEdge,_higherEdgePrice,_lowerEdgePrice,clrAliceBlue);
|
||||
|
||||
if(candleClosedBelowSupportZone(_timeFrame))
|
||||
{
|
||||
Comment("Im taking a sell !");
|
||||
if(((indexToNewTrade = findAvailableSpotInSellManagerArr())!= -1))
|
||||
{
|
||||
|
||||
|
||||
double stopLossPrice ;
|
||||
if(currentResistanceHighEdge != -1)
|
||||
{
|
||||
// stopLossPrice = currentResistanceHighEdge + stopLossAboveWickByActual ;
|
||||
stopLossPrice = lastHighFractalPrice + stopLossAboveWickByActual;
|
||||
}
|
||||
//stopLossPrice = iHigh(_Symbol,_timeFrame,1) + stopLossAboveWickByActual;
|
||||
|
||||
if(stopLossIsValidSells(stopLossPrice,maxPipsRiskAmountActual))
|
||||
{
|
||||
double stopLossInPips = stopLossPrice - SymbolInfoDouble(_Symbol,SYMBOL_BID) ;
|
||||
double netTp = rrFactor * stopLossInPips ;
|
||||
double lotsToTrade = lsCalc.calculateLotSize(riskDollars,stopLossPrice);
|
||||
activeTradeId = sellEntryManager.takeSellTradeTiger(lotsToTrade,stopLossPrice,SymbolInfoDouble(_Symbol,SYMBOL_BID)- netTp) ;
|
||||
|
||||
SellTradeManagerTiger* tempTigerManagerSell= new SellTradeManagerTiger(activeTradeId); // create an object of type sellTradeManagerTiger
|
||||
|
||||
tempTigerManagerSell.setBrokenSupportHigherEdge(currentSupportHighEdge);
|
||||
tempTigerManagerSell.setBrokenSupportLowerEdge(currentSupportLowerEdge);
|
||||
SellActiveTradesArray[indexToNewTrade] = tempTigerManagerSell ;// put the new object in the array
|
||||
|
||||
sellsCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("stop loss is not valid sells!");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Comment("i cant take a trade because the arrray is full");
|
||||
}
|
||||
|
||||
currentSupportLowerEdge = -1;
|
||||
currentSupportHighEdge = -1 ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
if(isHighFractalByIndex(fractalsPeriod+1,fractalsPeriod,fractalsPeriod,_timeFrame)) // RESISTANCES
|
||||
{
|
||||
objectsManager.drawHighFractal(fractalsPeriod+1,clrAliceBlue);
|
||||
lastHighFractalPrice = iHigh(_Symbol,PERIOD_CURRENT,fractalsPeriod+1);
|
||||
currentResistanceZonePrice = detectResistanceFromLastHighFractal(fractalsPeriod+5);
|
||||
|
||||
datetime _leftEdge = iTime(_Symbol,PERIOD_CURRENT,fractalsPeriod+1);
|
||||
datetime _rightEdge =rightEdge;
|
||||
double _higherEdgePrice = currentResistanceZonePrice + resistanceExtendAboveCandleActual;
|
||||
double _lowerEdgePrice = currentResistanceZonePrice - resistanceLowerEdgeExtendActual;
|
||||
|
||||
currentResistanceHighEdge = _higherEdgePrice;
|
||||
currentResistanceLowEdge = _lowerEdgePrice;
|
||||
Zone* supportZoneObject = new Zone("resistance_zone",_higherEdgePrice,_lowerEdgePrice,_leftEdge,_rightEdge,_timeFrameStr,"TYPE_RESISTANCE_BREAKOUT");
|
||||
objectsManager.drawRectangleInStrategyTester(2,_leftEdge,_rightEdge,_higherEdgePrice,_lowerEdgePrice,clrAliceBlue);
|
||||
|
||||
if(candleClosedAboveResistanceZone(_timeFrame))
|
||||
{
|
||||
Comment("Im taking a buy !");
|
||||
|
||||
if(((indexToNewTrade = findAvailableSpotInBuyManagerArr()) != -1))
|
||||
{
|
||||
|
||||
Print("indexToNewTrade:--------------------------------------- " + indexToNewTrade);
|
||||
double stopLossPrice ;
|
||||
if(currentSupportLowerEdge != -1)
|
||||
{
|
||||
// stopLossPrice = currentSupportLowerEdge - stopLossUnderWickByActual ;
|
||||
stopLossPrice = lastLowFractalPrice - stopLossUnderWickByActual ;
|
||||
}
|
||||
|
||||
//stopLossPrice = iLow(_Symbol,_timeFrame,1) - stopLossUnderWickByActual; // if there is no lower zone , take the last m30 candle's low
|
||||
|
||||
if(stopLossIsValidBuys(stopLossPrice,maxPipsRiskAmountActual))
|
||||
{
|
||||
double stopLossInPips = SymbolInfoDouble(_Symbol,SYMBOL_ASK) - stopLossPrice ;
|
||||
double netTp = rrFactor * stopLossInPips ;
|
||||
double lotsToTrade = lsCalc.calculateLotSize(riskDollars,stopLossPrice);
|
||||
activeTradeId = buyEntryManager.takeBuyTradeTiger(lotsToTrade,stopLossPrice,SymbolInfoDouble(_Symbol,SYMBOL_ASK)+ netTp) ;
|
||||
|
||||
BuyTradeManagerTiger* tempTigerManagerBuy= new BuyTradeManagerTiger(activeTradeId); // create an object of type sellTradeManagerTiger
|
||||
tempTigerManagerBuy.setBrokenResistanceHigherEdge(currentResistanceHighEdge);
|
||||
tempTigerManagerBuy.setBrokenResistancetLowerEdge(currentResistanceLowEdge);
|
||||
BuyActiveTradesArray[indexToNewTrade] = tempTigerManagerBuy ;// put the new object in the array
|
||||
|
||||
buysCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("stop loss is not valid buys !");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Comment("i cant take a trade because the arrray is full");
|
||||
}
|
||||
|
||||
currentResistanceHighEdge = -1;
|
||||
currentResistanceLowEdge = -1 ;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool candleClosedBelowSupportZone(ENUM_TIMEFRAMES _timeFrame)
|
||||
{
|
||||
if(candleClosedBearish(_timeFrame,1) && (iClose(_Symbol,_timeFrame,1) < currentSupportLowerEdge) && (currentSupportLowerEdge != -1) && (currentSupportZonePrice != 99999))
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool candleClosedAboveResistanceZone(ENUM_TIMEFRAMES _timeFrame)
|
||||
{
|
||||
|
||||
if(candleClosedBullish(_timeFrame,1) && (iClose(_Symbol,_timeFrame,1) > currentResistanceHighEdge) && (currentResistanceHighEdge != -1) && (currentResistanceZonePrice != 0))
|
||||
{
|
||||
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int findAvailableSpotInBuyManagerArr() // returns the index , or -1 if all are full
|
||||
{
|
||||
|
||||
for(int i=0 ; i < NUM_MAX_ALLOWED_TRADES ; i++)
|
||||
{
|
||||
if(BuyActiveTradesArray[i] == NULL)
|
||||
{
|
||||
return i;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int findAvailableSpotInSellManagerArr() // returns the index , or -1 if all are full
|
||||
{
|
||||
|
||||
for(int i=0 ; i<NUM_MAX_ALLOWED_TRADES ; i++)
|
||||
{
|
||||
if(SellActiveTradesArray[i] == NULL)
|
||||
{
|
||||
|
||||
return i ;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void cleanBuyTradesArr()
|
||||
{
|
||||
|
||||
for(int i=0 ; i< NUM_MAX_ALLOWED_TRADES ; i++) // iterate over the trade managers array
|
||||
{
|
||||
//Print("arrived here iteration " + i);
|
||||
bool currentPositionFound = false ;
|
||||
for(int j = 0 ; j < PositionsTotal() ; j++) // iterate over all the active positions
|
||||
{
|
||||
//Print("arrived here iteration " + j);
|
||||
ulong posTicket = PositionGetTicket(j);
|
||||
if((BuyActiveTradesArray[i] != NULL) && (BuyActiveTradesArray[i].getTradeId() == posTicket)) // found the current trade , in the active trades.
|
||||
{
|
||||
currentPositionFound = true ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(!currentPositionFound)
|
||||
{
|
||||
if(BuyActiveTradesArray[i]!= NULL)
|
||||
{
|
||||
Print("Cleaned the position with the id of: "+ BuyActiveTradesArray[i].getTradeId());
|
||||
}
|
||||
|
||||
delete BuyActiveTradesArray[i] ; // free the allocated memory for the object
|
||||
BuyActiveTradesArray[i] = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void cleanSellTradesArr()
|
||||
{
|
||||
|
||||
for(int i=0 ; i< NUM_MAX_ALLOWED_TRADES ; i++) // iterate over the trade managers array
|
||||
{
|
||||
bool currentPositionFound = false ;
|
||||
for(int j = 0 ; j< PositionsTotal() ; j++) // iterate over all the active positions
|
||||
{
|
||||
ulong posTicket = PositionGetTicket(j);
|
||||
if((SellActiveTradesArray[i] != NULL) && (SellActiveTradesArray[i].getTradeId() == posTicket)) // found the current trade , in the active trades.
|
||||
{
|
||||
currentPositionFound = true ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(!currentPositionFound)
|
||||
{
|
||||
|
||||
delete SellActiveTradesArray[i] ; // free the allocated memory for the object
|
||||
SellActiveTradesArray[i] = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void manageRiskIfNeededPhoenix()
|
||||
{
|
||||
|
||||
for(int i=0; i<NUM_MAX_ALLOWED_TRADES; i++)
|
||||
{
|
||||
if(BuyActiveTradesArray[i] != NULL)
|
||||
{
|
||||
if(candleClosedBearish(PERIOD_M5,1) && (iClose(_Symbol,PERIOD_M5,1) < BuyActiveTradesArray[i].getBrokenResistanceLowerEdge()))
|
||||
{
|
||||
BuyActiveTradesArray[i].incrementRiskManagementCandleCoutner();
|
||||
Print("risk managment candle coutn is :" + BuyActiveTradesArray[i].getRiskManagementCandleCounter());
|
||||
}
|
||||
else
|
||||
if((iClose(_Symbol,PERIOD_M5,1)) > BuyActiveTradesArray[i].getBrokenResistanceHigherEdge())
|
||||
{
|
||||
BuyActiveTradesArray[i].setRiskManagementCandleCounter(0);
|
||||
}
|
||||
|
||||
if(BuyActiveTradesArray[i].getRiskManagementCandleCounter() >= riskManagementCandlesCount)
|
||||
{
|
||||
// Close the trade
|
||||
tradeLong.PositionClose(BuyActiveTradesArray[i].getTradeId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if(SellActiveTradesArray[i] != NULL)
|
||||
{
|
||||
if(candleClosedBullish(PERIOD_M5,1) && (iClose(_Symbol,PERIOD_M5,1) > SellActiveTradesArray[i].getBrokenSupportHigherEdge()))
|
||||
{
|
||||
SellActiveTradesArray[i].incrementRiskManagementCandleCoutner();
|
||||
|
||||
}
|
||||
else
|
||||
if((iClose(_Symbol,PERIOD_M5,1)) < SellActiveTradesArray[i].getBrokenSupportLowerEdge())
|
||||
{
|
||||
SellActiveTradesArray[i].setRiskManagementCandleCounter(0);
|
||||
}
|
||||
|
||||
if(SellActiveTradesArray[i].getRiskManagementCandleCounter() >= riskManagementCandlesCount)
|
||||
{
|
||||
// Close the trade
|
||||
tradeShort.PositionClose(SellActiveTradesArray[i].getTradeId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double calculateStopLossBasedOnFractalsBuys(int _fractalsPeriod, ENUM_TIMEFRAMES _timeFrame)
|
||||
{
|
||||
|
||||
|
||||
|
||||
for(int i=0 ; 300 ; i++) // scan the last 200 candles
|
||||
{
|
||||
if(isLowFractalByIndex(i,_fractalsPeriod,_fractalsPeriod,_timeFrame))
|
||||
{
|
||||
|
||||
return iLow(_Symbol,_timeFrame,i);
|
||||
}
|
||||
}
|
||||
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double calculateStopLossBasedOnFractalsSells(int _fractalsPeriod,ENUM_TIMEFRAMES _timeFrame)
|
||||
{
|
||||
for(int i=0 ; 300 ; i++) // scan the last 200 candles
|
||||
{
|
||||
if(isHighFractalByIndex(i,_fractalsPeriod,_fractalsPeriod,_timeFrame))
|
||||
{
|
||||
return iHigh(_Symbol,_timeFrame,i);
|
||||
}
|
||||
}
|
||||
|
||||
return -1 ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
void trailAllOpenPositionsIfNeeded(ENUM_TIMEFRAMES _timeFrame)
|
||||
{
|
||||
|
||||
for(int i=0 ; i< NUM_MAX_ALLOWED_TRADES ; i++) // CHECK TRAIL FOR BUYS
|
||||
{
|
||||
if((BuyActiveTradesArray[i] != NULL))
|
||||
{
|
||||
double newStopLoss = iLow(_Symbol,_timeFrame,1);
|
||||
newStopLoss = newStopLoss - stopLossUnderWickByActual ;
|
||||
if(newStopLoss > positionStopLoss(BuyActiveTradesArray[i].getTradeId())) // if new stop loss is higher than the current position's stop loss
|
||||
{
|
||||
if(SymbolInfoDouble(_Symbol,SYMBOL_BID) <= newStopLoss){ // close the trade because the bid is lower than the stop loss (and the modify will fail))
|
||||
tradeLong.PositionClose(BuyActiveTradesArray[i].getTradeId());
|
||||
}
|
||||
positionTrailStopLoss(BuyActiveTradesArray[i].getTradeId(),newStopLoss,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if((SellActiveTradesArray[i] != NULL)) // CHECK TRAIL FOR SELLS
|
||||
{
|
||||
double newStopLoss = iHigh(_Symbol,_timeFrame,1);
|
||||
newStopLoss = newStopLoss + stopLossAboveWickByActual ;
|
||||
if(newStopLoss < positionStopLoss(SellActiveTradesArray[i].getTradeId())) // if new stop loss is lower than the current position's stop loss
|
||||
{
|
||||
if(SymbolInfoDouble(_Symbol,SYMBOL_ASK) >= newStopLoss){ // close the trade because the ask is higher than the stop loss (and the modify will fail))
|
||||
tradeShort.PositionClose(SellActiveTradesArray[i].getTradeId());
|
||||
}
|
||||
positionTrailStopLoss(SellActiveTradesArray[i].getTradeId(),newStopLoss,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,201 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Phoenix_Reborn.mq5 |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include "Phoenix_Functions.mqh"
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
|
||||
int OnInit()
|
||||
{
|
||||
//---
|
||||
|
||||
//---
|
||||
iOpen(_Symbol,PERIOD_M5,1);
|
||||
iOpen(_Symbol,PERIOD_M15,1);
|
||||
iOpen(_Symbol,PERIOD_M30,1);
|
||||
iOpen(_Symbol,PERIOD_H1,1);
|
||||
iOpen(_Symbol,PERIOD_H4,1);
|
||||
|
||||
for(int i=0; i<NUM_MAX_ALLOWED_TRADES ; i++)
|
||||
{
|
||||
BuyActiveTradesArray[i] = NULL ;
|
||||
SellActiveTradesArray[i] = NULL ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
objectsManager.addTextTiger();
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//---
|
||||
Print("Buys Count: " + buysCount);
|
||||
Print("Sells Count: " + sellsCount);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//---
|
||||
cleanBuyTradesArr();
|
||||
cleanSellTradesArr();
|
||||
|
||||
|
||||
|
||||
/*if(newCandleDetectorM1.isNewCandle()){
|
||||
|
||||
datetime currTime = TimeCurrent();
|
||||
Comment(TimeToString(currTime,TIME_MINUTES) + ": Sell Below: " + currentSupportLowerEdge + " Buy Above: "+ currentResistanceHighEdge);
|
||||
|
||||
findAndDrawFractalsAndZones(PERIOD_M1,"PERIOD_M1");
|
||||
|
||||
if(candleClosedBelowSupportZone()){
|
||||
datetime currTime = TimeCurrent();
|
||||
|
||||
Comment(TimeToString(currTime,TIME_MINUTES) + ": im taking a sell !");
|
||||
|
||||
|
||||
if(((indexToNewTrade = findAvailableSpotInSellManagerArr()) != -1 ) )
|
||||
{
|
||||
|
||||
Print("indexToNewTrade: ----------------------------------------------" + indexToNewTrade);
|
||||
double stopLossPrice ;
|
||||
if(currentResistanceHighEdge != -1){
|
||||
stopLossPrice = currentResistanceHighEdge + stopLossAboveWickBy ;
|
||||
}
|
||||
else{
|
||||
stopLossPrice = iHigh(_Symbol,PERIOD_M30,1) - stopLossAboveWickBy; // if there is no higher zone , take the last m30 candle's high
|
||||
}
|
||||
activeTradeId = sellEntryManager.takeSellTradeTiger(lotSize,stopLossPrice,SymbolInfoDouble(_Symbol,SYMBOL_BID)- netTakeProfit ) ;
|
||||
|
||||
SellTradeManagerTiger* tempTigerManagerSell= new SellTradeManagerTiger(activeTradeId); // create an object of type sellTradeManagerTiger
|
||||
|
||||
tempTigerManagerSell.setBrokenSupportHigherEdge(currentSupportHighEdge);
|
||||
tempTigerManagerSell.setBrokenSupportLowerEdge(currentSupportLowerEdge);
|
||||
SellActiveTradesArray[indexToNewTrade] = tempTigerManagerSell ;// put the new object in the array
|
||||
|
||||
sellsCount++;
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Comment("i cant take a trade because the arrray is full");
|
||||
}
|
||||
|
||||
currentSupportLowerEdge = -1;
|
||||
currentSupportHighEdge = -1;
|
||||
}
|
||||
|
||||
|
||||
if(candleClosedAboveResistanceZone()){
|
||||
datetime currTime = TimeCurrent();
|
||||
Comment(TimeToString(currTime,TIME_MINUTES) + ": im taking a buy !");
|
||||
|
||||
|
||||
|
||||
if(((indexToNewTrade = findAvailableSpotInBuyManagerArr()) != -1))
|
||||
{
|
||||
|
||||
Print("indexToNewTrade:-------------------------------------------- " + indexToNewTrade);
|
||||
double stopLossPrice ;
|
||||
if(currentSupportLowerEdge != -1){
|
||||
stopLossPrice = currentSupportLowerEdge - stopLossUnderWickBy ;
|
||||
}
|
||||
else{
|
||||
stopLossPrice = iLow(_Symbol,PERIOD_M30,1) - stopLossUnderWickBy; // if there is no lower zone , take the last m30 candle's low
|
||||
}
|
||||
activeTradeId = buyEntryManager.takeBuyTradeTiger(lotSize,stopLossPrice,SymbolInfoDouble(_Symbol,SYMBOL_ASK)+ netTakeProfit ) ;
|
||||
|
||||
BuyTradeManagerTiger* tempTigerManagerBuy= new BuyTradeManagerTiger(activeTradeId); // create an object of type sellTradeManagerTiger
|
||||
tempTigerManagerBuy.setBrokenResistanceHigherEdge(currentResistanceHighEdge);
|
||||
tempTigerManagerBuy.setBrokenResistancetLowerEdge(currentResistanceLowEdge);
|
||||
BuyActiveTradesArray[indexToNewTrade] = tempTigerManagerBuy ;// put the new object in the array
|
||||
buysCount++;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Comment("i cant take a trade because the arrray is full");
|
||||
}
|
||||
|
||||
currentResistanceHighEdge = -1;
|
||||
currentResistanceLowEdge = -1;
|
||||
}
|
||||
} */
|
||||
|
||||
|
||||
/*if(newCandleDetectorM5.isNewCandle()){
|
||||
findAndDrawFractalsAndZones(PERIOD_M5,"PERIOD_M5");
|
||||
int tradeCount = 0 ;
|
||||
for(int i=0;i<NUM_MAX_ALLOWED_TRADES;i++){
|
||||
if(BuyActiveTradesArray[i]!= NULL){
|
||||
tradeCount++ ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
manageRiskIfNeededPhoenix();
|
||||
} */
|
||||
|
||||
|
||||
/*if(newCandleDetectorM30.isNewCandle()){
|
||||
findAndDrawFractalsAndZones(PERIOD_M30,"PERIOD_M30");
|
||||
int tradeCount = 0 ;
|
||||
for(int i=0;i<NUM_MAX_ALLOWED_TRADES;i++){
|
||||
if(BuyActiveTradesArray[i]!= NULL){
|
||||
tradeCount++ ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
datetime currTime = TimeCurrent();
|
||||
ObjectSetString(0,"clockTextTiger",OBJPROP_TEXT,TimeToString(currTime,TIME_MINUTES));
|
||||
} */
|
||||
|
||||
|
||||
if(newCandleDetectorH4.isNewCandle()){
|
||||
findAndDrawFractalsAndZones(PERIOD_H4,"PERIOD_H4");
|
||||
int tradeCount = 0 ;
|
||||
|
||||
|
||||
|
||||
datetime currTime = TimeCurrent();
|
||||
ObjectSetString(0,"clockTextTiger",OBJPROP_TEXT,TimeToString(currTime,TIME_MINUTES));
|
||||
}
|
||||
|
||||
|
||||
if(newCandleDetectorDaily.isNewCandle()){
|
||||
|
||||
// objectsManager.drawVerticalLine(clrAqua, TimeCurrent());
|
||||
}
|
||||
|
||||
if(newCandleDetectorWeekly.isNewCandle()){
|
||||
|
||||
objectsManager.drawVerticalLine(clrRed, TimeCurrent());;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,51 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Point_Value_Testing.mq5 |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
#property script_show_inputs
|
||||
//--- day of week
|
||||
enum Confirmation_HTF
|
||||
{
|
||||
H4_Break= 0,
|
||||
H4_Closure = 1,
|
||||
};
|
||||
//--- input parameters
|
||||
input Confirmation_HTF H4_CONFIRMATION ;
|
||||
|
||||
input int someNumber ;
|
||||
int OnInit()
|
||||
{
|
||||
//---
|
||||
|
||||
//---
|
||||
if(!ChartScreenShot(0,"somefile.png",1260,720,ALIGN_CENTER)){
|
||||
Print("failed to take screenshot , Error: " + GetLastError());
|
||||
}
|
||||
Print("Point value of this pair :" + Point());
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,119 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| SellEntryManager.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
|
||||
#include "SellRejectionDetector.mqh"
|
||||
#include <Trade/Trade.mqh>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
CTrade tradeShort ;
|
||||
|
||||
class SellEntryManager
|
||||
{
|
||||
private:
|
||||
|
||||
bool shortTradeTaken ;
|
||||
bool waitingForRejectionCandle ;
|
||||
bool waitingForRetracement ;
|
||||
bool liquiditySweepEntryTaken ;
|
||||
|
||||
public:
|
||||
SellEntryManager();
|
||||
~SellEntryManager();
|
||||
|
||||
SellRejectionDetector* sellRejectionDetector ;
|
||||
|
||||
bool isWaitingForRejectionCandle(){return waitingForRejectionCandle ;}
|
||||
void setWaitingForRejectionCandle(bool _setting){waitingForRejectionCandle = _setting ; }
|
||||
|
||||
bool isWaitingForRetracement(){return waitingForRetracement;}
|
||||
void setWaitingForRetracement(bool _setting){waitingForRetracement = _setting ;}
|
||||
|
||||
|
||||
bool sellTradeTaken();
|
||||
void setTradeTakenStatus(bool _status){shortTradeTaken = _status ;}
|
||||
|
||||
bool liqEntryIsTaken(){return liquiditySweepEntryTaken;}
|
||||
void setLiquiditySweepEntryTaken(bool _entryStatus){liquiditySweepEntryTaken = _entryStatus ;}
|
||||
|
||||
|
||||
|
||||
|
||||
ulong takeSellTrade(double _lots,double _stopLoss);
|
||||
ulong takeSellTradeTiger(double _lots, double _stopLoss, double _takeProfit);
|
||||
ulong takeSellTradeTiger(double _lots, double _stopLoss);
|
||||
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
SellEntryManager::SellEntryManager()
|
||||
{
|
||||
|
||||
sellRejectionDetector = new SellRejectionDetector();
|
||||
shortTradeTaken = false ;
|
||||
waitingForRejectionCandle = false ;
|
||||
bool waitingForRetracement = false;
|
||||
liquiditySweepEntryTaken = false;
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
SellEntryManager::~SellEntryManager()
|
||||
{
|
||||
delete sellRejectionDetector;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
bool SellEntryManager:: sellTradeTaken(){
|
||||
|
||||
return shortTradeTaken ;
|
||||
}
|
||||
|
||||
ulong SellEntryManager:: takeSellTrade(double _lots, double _stopLoss){
|
||||
|
||||
tradeShort.Sell(NormalizeDouble(_lots,2),_Symbol,SymbolInfoDouble(_Symbol, SYMBOL_BID),_stopLoss);
|
||||
ulong tradeTicket = tradeShort.ResultOrder();
|
||||
|
||||
Print("Sell entry manager has taken a trade, ticket: " + tradeTicket);
|
||||
return tradeTicket;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
ulong SellEntryManager:: takeSellTradeTiger(double _lots, double _stopLoss, double _takeProfit){
|
||||
|
||||
double netTp = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
netTp = netTp - _takeProfit ;
|
||||
|
||||
tradeShort.Sell(NormalizeDouble(_lots,2),_Symbol,SymbolInfoDouble(_Symbol, SYMBOL_BID),_stopLoss,SymbolInfoDouble(_Symbol, SYMBOL_BID) - netTp);
|
||||
|
||||
|
||||
ulong tradeTicket = tradeShort.ResultOrder();
|
||||
|
||||
Print("sELL entry manager has taken a trade, ticket: " + tradeTicket);
|
||||
return tradeTicket;
|
||||
|
||||
}
|
||||
|
||||
|
||||
ulong SellEntryManager:: takeSellTradeTiger(double _lots, double _stopLoss){
|
||||
|
||||
tradeShort.Sell(NormalizeDouble(_lots,2),_Symbol,SymbolInfoDouble(_Symbol, SYMBOL_BID),_stopLoss);
|
||||
ulong tradeTicket = tradeShort.ResultOrder();
|
||||
Print("sELL entry manager has taken a trade, ticket: " + tradeTicket);
|
||||
return tradeTicket;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| SellGandalf.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
|
||||
#include <Trade/Trade.mqh>
|
||||
|
||||
CTrade tradeShort ;
|
||||
|
||||
class SellGandalf
|
||||
{
|
||||
private:
|
||||
bool shortTradeTaken ;
|
||||
ulong longTrades[10] ;
|
||||
|
||||
public:
|
||||
SellGandalf();
|
||||
~SellGandalf();
|
||||
|
||||
bool sellTradeTaken();
|
||||
void setTradeTakenStatus(bool _status){shortTradeTaken = _status ; Print("long trade taken flag has been set to true");}
|
||||
|
||||
|
||||
ulong takeSellTrade(double _lots,double _stopLoss);
|
||||
ulong takeSellTradeGandalf(double _lots,double _stopLoss);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
SellGandalf::SellGandalf()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
SellGandalf::~SellGandalf()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
bool SellGandalf:: sellTradeTaken(){
|
||||
|
||||
|
||||
return shortTradeTaken ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ulong SellGandalf:: takeSellTrade(double _lots, double _stopLoss){
|
||||
|
||||
tradeShort.Sell(NormalizeDouble(_lots,2),_Symbol,SymbolInfoDouble(_Symbol, SYMBOL_BID),_stopLoss);
|
||||
|
||||
ulong tradeTicket = tradeShort.ResultOrder();
|
||||
|
||||
Print("Sell entry manager has taken a trade, ticket: " + tradeTicket);
|
||||
return tradeTicket;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
ulong SellGandalf:: takeSellTradeGandalf(double _lots,double _stopLoss){
|
||||
|
||||
tradeShort.Sell(NormalizeDouble(_lots,2),_Symbol,SymbolInfoDouble(_Symbol, SYMBOL_BID),_stopLoss);
|
||||
|
||||
ulong tradeTicket = tradeShort.ResultOrder();
|
||||
|
||||
Print("Sell entry manager has taken a trade, ticket: " + tradeTicket);
|
||||
return tradeTicket;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| SellRejectionDetector.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
class SellRejectionDetector
|
||||
{
|
||||
private:
|
||||
|
||||
public:
|
||||
SellRejectionDetector();
|
||||
~SellRejectionDetector();
|
||||
|
||||
bool rejectionByOneCandleFormed(ENUM_TIMEFRAMES _timeFrame);
|
||||
bool rejectionByRangeFormed();
|
||||
bool rejectionByWicksFormed();
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
SellRejectionDetector::SellRejectionDetector()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
SellRejectionDetector::~SellRejectionDetector()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
bool SellRejectionDetector:: rejectionByOneCandleFormed(ENUM_TIMEFRAMES _timeFrame){
|
||||
|
||||
double rejectionCandleClose = iClose(_Symbol,_timeFrame,1);
|
||||
double rejectionCandleOpen = iOpen(_Symbol,_timeFrame,1);
|
||||
double rejectionCandleLow = iLow(_Symbol,_timeFrame,1);
|
||||
double rejectionCandleLowerWickSize ;
|
||||
double rejectionCandleBodySize;
|
||||
|
||||
if(rejectionCandleOpen > rejectionCandleClose){ // the previous candle closed bearish
|
||||
rejectionCandleLowerWickSize = rejectionCandleClose - rejectionCandleLow ;
|
||||
rejectionCandleBodySize = rejectionCandleOpen - rejectionCandleClose;
|
||||
if(rejectionCandleBodySize >= rejectionCandleLowerWickSize){
|
||||
return true ;
|
||||
}
|
||||
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
@@ -0,0 +1,586 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| SellTradeManager.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
//#include <Telegram_Handler.mqh>
|
||||
#include <TradeManagersAttributes.mqh>
|
||||
#include <Trade/Trade.mqh>
|
||||
CTrade tradeInTradeManager;
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
class SellTradeManager
|
||||
{
|
||||
private:
|
||||
int tradeId ;
|
||||
ulong rejectionByOneCandleTradeArray[3]; // index 0 : half the contract , index 1 : quarter of the contract , index 2 : quarter of the contract
|
||||
|
||||
|
||||
string firstSecureMethod ;
|
||||
bool firstSecureMethodFound;
|
||||
int numberOfTakeProfits ;
|
||||
bool securedFirstLevelProfit ;
|
||||
bool securedSecondLevelProfit;
|
||||
double partialToClose ;
|
||||
bool isTradeRunning ;
|
||||
|
||||
|
||||
public:
|
||||
SellTradeManager();
|
||||
~SellTradeManager();
|
||||
|
||||
|
||||
void fillRejectionByOneCandleTradeArray(int _index, ulong _id) {rejectionByOneCandleTradeArray[_index] = _id ;}
|
||||
ulong getRejectionByOneCandleTradeTicket(int _index) {return rejectionByOneCandleTradeArray[_index] ;}
|
||||
void printRejectionByOneCandleTradeArray();
|
||||
|
||||
void checkAndSecureTradeIfNeeded(double _ratio, double _riskInDollars);
|
||||
string findFirstSecureMethod();
|
||||
|
||||
bool reachedProfitRatio(int _indexInArr);
|
||||
bool closeTrade(int _indexInArr);
|
||||
bool positionBreakEven(int _indexInArr);
|
||||
|
||||
void addTpAtIndex(int _index, double tpPrice) {tpArray[_index] = tpPrice;}
|
||||
int countRemainingTakeProfits();
|
||||
bool reachedClosestTakeProfit();
|
||||
void deleteClosestTp();
|
||||
int findClosestTpIndex();
|
||||
|
||||
void cleanOrderDataStructures();
|
||||
|
||||
void setTradeRunning(bool _setting) {isTradeRunning = _setting ;}
|
||||
bool tradeIsRunning() {return isTradeRunning ;}
|
||||
|
||||
double tpArray[3];
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
SellTradeManager::SellTradeManager()
|
||||
{
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
tpArray[i] = -1;
|
||||
}
|
||||
securedFirstLevelProfit = false ;
|
||||
securedSecondLevelProfit = false ;
|
||||
firstSecureMethodFound = false ;
|
||||
firstSecureMethod = "NOT_FOUND" ;
|
||||
partialToClose = -1 ;
|
||||
isTradeRunning = false ;
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
SellTradeManager::~SellTradeManager()
|
||||
{
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
void SellTradeManager:: printRejectionByOneCandleTradeArray()
|
||||
{
|
||||
|
||||
Print("Printing the tickets :");
|
||||
for(int i=0 ; i<3 ; i++)
|
||||
{
|
||||
Print((int)rejectionByOneCandleTradeArray[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void SellTradeManager:: checkAndSecureTradeIfNeeded(double _ratio, double _riskInDollars)
|
||||
{
|
||||
|
||||
|
||||
if(securedFirstLevelProfit == false) // in this case im searching for 2 cases: either RR 1:1.5 , OR reaching the first TP , if any of them happened im gonna close half the order and updatae the remaining stop losses
|
||||
{
|
||||
|
||||
|
||||
if(!firstSecureMethodFound)
|
||||
{
|
||||
|
||||
firstSecureMethod = findFirstSecureMethod();
|
||||
if(firstSecureMethod != "FAILED")
|
||||
{
|
||||
firstSecureMethodFound = true ;
|
||||
}
|
||||
else
|
||||
if(firstSecureMethod == "FAILED")
|
||||
{
|
||||
Print("Failed to find the first secure method, go check the function : findFirstSecureMehod() !");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(firstSecureMethodFound == true)
|
||||
{
|
||||
|
||||
if(firstSecureMethod == "RATIO_METHOD")
|
||||
{
|
||||
cleanOrderDataStructures(); // this is used each time before we are choosing an order by ticket
|
||||
if(reachedProfitRatio(0))
|
||||
{
|
||||
ChartRedraw(); // Make sure the chart is up to date
|
||||
ChartScreenShot(0, fileName, 1024, 768, ALIGN_RIGHT);
|
||||
SendTelegramMessage(TelegramApiUrl, TelegramBotToken, ChatId,
|
||||
"If you see this message it means we reached the first secure method, which is ratio method, after this message, half of the order must be closed (2 trades will remain active), and the first quarter will be put into Break even " + TimeToString(TimeLocal()), fileName);
|
||||
if(closeTrade(0)) // close the half
|
||||
{
|
||||
|
||||
rejectionByOneCandleTradeArray[0] = -1;
|
||||
Print("Closed Half Of the position due to reaching the first secure Ratio!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed Closing Half of the order by reaching the first secure Ratio !");
|
||||
}
|
||||
|
||||
cleanOrderDataStructures(); // this is used each time before we are choosing an order by ticket
|
||||
if(positionBreakEven(1)) // put the first quarter at break even
|
||||
{
|
||||
|
||||
Print(" First quarter has been put into break even due to reaching the first secure Ratio!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to Put the first quarter into break even");
|
||||
}
|
||||
|
||||
numberOfTakeProfits = countRemainingTakeProfits();
|
||||
|
||||
Print("Number of remaining tps is: " + numberOfTakeProfits);
|
||||
|
||||
securedFirstLevelProfit = true ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
if(firstSecureMethod == "FIRST_TP_METHOD")
|
||||
{
|
||||
if(countRemainingTakeProfits() > 1) // there is at least 2 tp in the tp Array (because if this is the last tp then we want to close the whole order and not just a part of it)
|
||||
{
|
||||
if(reachedClosestTakeProfit()) // 2. Check if reached the first Tp
|
||||
{
|
||||
ChartRedraw(); // Make sure the chart is up to date
|
||||
ChartScreenShot(0, fileName, 1024, 768, ALIGN_RIGHT);
|
||||
SendTelegramMessage(TelegramApiUrl, TelegramBotToken, ChatId,
|
||||
"If you see this message it means we reached the first secure method which is tp1, after this message, half of the order must be closed (2 trades will remain active), and the first quarter will be put into Break even " + TimeToString(TimeLocal()), fileName);
|
||||
// close the first half and update remaining partials sl's and delete the closest take profit from the array
|
||||
cleanOrderDataStructures(); // this is used each time before we are choosing an order by ticket
|
||||
if(closeTrade(0)) // close the half
|
||||
{
|
||||
|
||||
rejectionByOneCandleTradeArray[0] = -1;
|
||||
Print("Closed Half Of the position due to reaching the first TP!");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed Closing Half of the order by reaching the first TP !");
|
||||
}
|
||||
cleanOrderDataStructures(); // this is used each time before we are choosing an order by ticket
|
||||
if(positionBreakEven(1)) // put the first quarter at break even
|
||||
{
|
||||
|
||||
Print(" First quarter has been put into break even due to reaching the first TP!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to Put the first quarter into break even");
|
||||
}
|
||||
deleteClosestTp();
|
||||
numberOfTakeProfits = countRemainingTakeProfits(); // update the number of remaining take profits
|
||||
// calculate the remaining tps
|
||||
|
||||
Print("Number of remaining tps is: " + numberOfTakeProfits);
|
||||
|
||||
securedFirstLevelProfit = true ;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
if(numberOfTakeProfits = countRemainingTakeProfits() == 1)
|
||||
{
|
||||
if(reachedClosestTakeProfit())
|
||||
{
|
||||
// close everything remained
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
if(securedFirstLevelProfit == true) // after securing the first level i just want to close the remaining partials by reaching the tp's
|
||||
{
|
||||
|
||||
if(countRemainingTakeProfits() == 1)
|
||||
{
|
||||
if(reachedClosestTakeProfit())
|
||||
{
|
||||
// close everything
|
||||
cleanOrderDataStructures();
|
||||
for(int i=0 ; i<3 ; i++)
|
||||
{
|
||||
closeTrade(i);
|
||||
}
|
||||
Print("Closed every thing because price reached the last Take Profit !");
|
||||
|
||||
ChartRedraw(); // Make sure the chart is up to date
|
||||
ChartScreenShot(0, fileName, 1024, 768, ALIGN_RIGHT);
|
||||
SendTelegramMessage(TelegramApiUrl, TelegramBotToken, ChatId,
|
||||
"If you see this message it means that all order are closed as a result of reaching the last tp " + TimeToString(TimeLocal()), fileName);
|
||||
deleteClosestTp();
|
||||
}
|
||||
}
|
||||
else
|
||||
if(countRemainingTakeProfits() > 1)
|
||||
{
|
||||
if(reachedClosestTakeProfit())
|
||||
{
|
||||
cleanOrderDataStructures();
|
||||
if(PositionSelectByTicket(rejectionByOneCandleTradeArray[1])) // DEALING WITH THE FIRST QUARTER
|
||||
{
|
||||
double currentLot = PositionGetDouble(POSITION_VOLUME);
|
||||
if(partialToClose == -1)
|
||||
{
|
||||
partialToClose = currentLot/numberOfTakeProfits ;
|
||||
}
|
||||
if(tradeInTradeManager.PositionClosePartial(rejectionByOneCandleTradeArray[1],NormalizeDouble(partialToClose,2)))
|
||||
{
|
||||
uint res = tradeInTradeManager.ResultRetcode();
|
||||
if(res == 10009)
|
||||
{
|
||||
Print("Closed Partials successfully on the first quarter !");
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("The returned code is: " + res + " go check what it means !");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to select position by ticket, Error: " + GetLastError());
|
||||
Print("The EA tried to close partials on the first quarter, but it is closed, probably due to break even and thats why it couldnt select the order !");
|
||||
}
|
||||
|
||||
|
||||
cleanOrderDataStructures();
|
||||
if(PositionSelectByTicket(rejectionByOneCandleTradeArray[2])) // DEALING WITH THE SECOND QUARTER
|
||||
{
|
||||
if(PositionGetDouble(POSITION_SL) > PositionGetDouble(POSITION_PRICE_OPEN)) // this is to put the second quarter at break even if its not already at break even
|
||||
{
|
||||
positionBreakEven(2);
|
||||
|
||||
}
|
||||
double currentLot = PositionGetDouble(POSITION_VOLUME);
|
||||
if(partialToClose == -1)
|
||||
{
|
||||
partialToClose = currentLot/numberOfTakeProfits ;
|
||||
}
|
||||
if(tradeInTradeManager.PositionClosePartial(rejectionByOneCandleTradeArray[2],NormalizeDouble(partialToClose,2)))
|
||||
{
|
||||
uint res = tradeInTradeManager.ResultRetcode();
|
||||
if(res == 10009)
|
||||
{
|
||||
Print("Closed Partials successfully on the second quarter!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("The returned code is: " + res + " go check what it means !");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
deleteClosestTp();
|
||||
Print("Number Of Remained tps is: " + countRemainingTakeProfits());
|
||||
|
||||
|
||||
ChartRedraw(); // Make sure the chart is up to date
|
||||
ChartScreenShot(0, fileName, 1024, 768, ALIGN_RIGHT);
|
||||
SendTelegramMessage(TelegramApiUrl, TelegramBotToken, ChatId,
|
||||
"If you see this message it means we reached a tp level (different than the first secure level), so partial positions will be closed, and the scond quarter must be in break even!" + TimeToString(TimeLocal()), fileName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
string SellTradeManager:: findFirstSecureMethod()
|
||||
{
|
||||
|
||||
cleanOrderDataStructures(); // this is used each time before we are choosing an order by ticket
|
||||
if(PositionSelectByTicket(rejectionByOneCandleTradeArray[0]))
|
||||
{
|
||||
double positionStopLoss = PositionGetDouble(POSITION_SL);
|
||||
double positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
double firstTakeProfit = tpArray[findClosestTpIndex()];
|
||||
if(((positionOpenPrice-firstTakeProfit)/(positionStopLoss-positionOpenPrice) > firstSecureRatio)) // firstTp > ratio
|
||||
{
|
||||
Print("Found the first profit secure method !");
|
||||
Print("The first TP RR is: 1:" + (positionOpenPrice-firstTakeProfit)/(positionStopLoss-positionOpenPrice) + "the firstSecureRatio is: 1:" + firstSecureRatio);
|
||||
Print("The tp ratio is greater than the firstSecure so:");
|
||||
Print("The first secure method is RATIO_METHOD");
|
||||
return"RATIO_METHOD";
|
||||
}
|
||||
else
|
||||
if((positionOpenPrice-firstTakeProfit)/(positionStopLoss-positionOpenPrice)< firstSecureRatio)
|
||||
{
|
||||
Print("Found the first profit secure method !");
|
||||
Print("The first TP RR is: 1:" + (positionOpenPrice-firstTakeProfit)/(positionStopLoss-positionOpenPrice) + "the firstSecureRatio is: 1:" + firstSecureRatio);
|
||||
Print("The tp ratio is less than the firstSecure so:");
|
||||
Print("The first secure method is FIRST_TP_METHOD");
|
||||
return "FIRST_TP_METHOD" ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to select position by ticket 1, Error: " + GetLastError());
|
||||
}
|
||||
|
||||
return "FAILED" ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool SellTradeManager:: reachedProfitRatio(int _indexInArr)
|
||||
{
|
||||
ulong _ticket = rejectionByOneCandleTradeArray[_indexInArr];
|
||||
if(_ticket != -1)
|
||||
{
|
||||
if(PositionSelectByTicket(_ticket))
|
||||
{
|
||||
if(PositionGetDouble(POSITION_PROFIT)/(0.5*riskDollars) >= firstSecureRatio) // checking if the first half of the contract reached the ratio of first secure profit
|
||||
{
|
||||
Print("reached profit ratio !");
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to select the position by ticket 4 ,Error: " + GetLastError());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool SellTradeManager:: closeTrade(int _indexInArr)
|
||||
{
|
||||
|
||||
|
||||
ulong _ticket = rejectionByOneCandleTradeArray[_indexInArr];
|
||||
if(_ticket != -1)
|
||||
{
|
||||
if(PositionSelectByTicket(_ticket))
|
||||
{
|
||||
|
||||
// close the first half and update remaining partials sl's
|
||||
if(tradeInTradeManager.PositionClose(_ticket))
|
||||
{
|
||||
return true ;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Print("Failed to close positon, Error:" + GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Print("Failed to select position by ticket 2, Error: "+ GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool SellTradeManager:: positionBreakEven(int _indexInArr)
|
||||
{
|
||||
|
||||
ulong _ticket = rejectionByOneCandleTradeArray[_indexInArr];
|
||||
if(_ticket != -1)
|
||||
{
|
||||
if(PositionSelectByTicket(_ticket)) // select the first quarter
|
||||
{
|
||||
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
double positionTp = PositionGetDouble(POSITION_TP);
|
||||
double positionSl = PositionGetDouble(POSITION_SL);
|
||||
|
||||
if(tradeInTradeManager.PositionModify((_ticket),openPrice,positionTp))
|
||||
{
|
||||
|
||||
|
||||
return true ;
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to modify oder , ERROR: " + GetLastError());
|
||||
return false ;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to select position by ticket 3");
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false ;
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int SellTradeManager:: countRemainingTakeProfits()
|
||||
{
|
||||
|
||||
int counter = 0 ;
|
||||
for(int i=0; i<3 ; i++)
|
||||
{
|
||||
if(tpArray[i] != -1)
|
||||
{
|
||||
counter++ ;
|
||||
}
|
||||
}
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void SellTradeManager:: deleteClosestTp()
|
||||
{
|
||||
|
||||
int closestTpIndex =findClosestTpIndex();
|
||||
tpArray[closestTpIndex] = -1;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int SellTradeManager:: findClosestTpIndex()
|
||||
{
|
||||
int closestTpIndex = 0;
|
||||
|
||||
for(int i=1; i<3; i++)
|
||||
{
|
||||
if(tpArray[i] > tpArray[closestTpIndex])
|
||||
{
|
||||
closestTpIndex = i ;
|
||||
}
|
||||
}
|
||||
|
||||
return closestTpIndex ;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool SellTradeManager:: reachedClosestTakeProfit()
|
||||
{
|
||||
|
||||
|
||||
double closestTakeProfitValue = tpArray[findClosestTpIndex()];
|
||||
//Print("im in reached closest take profit function ,the current price is: " + SymbolInfoDouble(_Symbol, SYMBOL_BID) + " and the tp is: " + closestTakeProfitValue);
|
||||
if(SymbolInfoDouble(_Symbol, SYMBOL_ASK) <= closestTakeProfitValue) // we want the ASK because we are basically buying the asset again (in a cheaper price), and we want to buy it on the ASK (which is the price that a seller is willing to sell us)
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void SellTradeManager:: cleanOrderDataStructures()
|
||||
{
|
||||
// this is to make sure, that every closed order is removed from the data strucutre !
|
||||
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
if(!PositionSelectByTicket(rejectionByOneCandleTradeArray[i]))
|
||||
{
|
||||
if(GetLastError() == 4753)
|
||||
{
|
||||
rejectionByOneCandleTradeArray[i] = -1 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,69 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| SellTradeManagerTiger.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
class SellTradeManagerTiger
|
||||
{
|
||||
private:
|
||||
ulong tradeId ;
|
||||
string entryType ;
|
||||
bool firstPartialSecured ;
|
||||
bool secondPartialSecured ;
|
||||
bool managedRisk ;
|
||||
int riskManagementCandleCounter ;
|
||||
double brokenSupportHigherEdge ;
|
||||
double brokenSupportLowerEdge ;
|
||||
public:
|
||||
ulong getTradeId(){return tradeId ;}
|
||||
|
||||
bool riskAlreadyManaged(){return managedRisk ;}
|
||||
void manageRisk(){managedRisk = true ;}
|
||||
|
||||
bool firstPartialIsSecured(){return firstPartialSecured ;}
|
||||
void secureFirstPartial(){firstPartialSecured = true ;}
|
||||
|
||||
bool retestWickFormed ;
|
||||
double retestWickLengthInPips ;
|
||||
|
||||
void setBrokenSupportHigherEdge(double _brokenSupportHigherEdge){brokenSupportHigherEdge = _brokenSupportHigherEdge ;}
|
||||
void setBrokenSupportLowerEdge(double _brokenSupportLowerEdge){brokenSupportLowerEdge = _brokenSupportLowerEdge ;}
|
||||
|
||||
double getBrokenSupportHigherEdge(){return brokenSupportHigherEdge ;}
|
||||
double getBrokenSupportLowerEdge(){return brokenSupportLowerEdge;}
|
||||
|
||||
void incrementRiskManagementCandleCoutner(){riskManagementCandleCounter++ ;}
|
||||
void decrementRiskManagementCandleCounter(){riskManagementCandleCounter-- ;}
|
||||
|
||||
int getRiskManagementCandleCounter(){return riskManagementCandleCounter ;}
|
||||
void setRiskManagementCandleCounter(int count){ riskManagementCandleCounter = count ;}
|
||||
|
||||
|
||||
SellTradeManagerTiger(ulong _tradeId);
|
||||
~SellTradeManagerTiger();
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
SellTradeManagerTiger::SellTradeManagerTiger(ulong _tradeId)
|
||||
{
|
||||
|
||||
tradeId = _tradeId ;
|
||||
firstPartialSecured = false ;
|
||||
secondPartialSecured = false ;
|
||||
managedRisk = false ;
|
||||
|
||||
retestWickFormed = false ;
|
||||
retestWickLengthInPips = 0 ;
|
||||
riskManagementCandleCounter = 0 ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
SellTradeManagerTiger::~SellTradeManagerTiger()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,29 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| SellTradeMangerTiger.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
class SellTradeMangerTiger
|
||||
{
|
||||
private:
|
||||
|
||||
public:
|
||||
SellTradeMangerTiger();
|
||||
~SellTradeMangerTiger();
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
SellTradeMangerTiger::SellTradeMangerTiger()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
SellTradeMangerTiger::~SellTradeMangerTiger()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,846 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ZoneScanner.mq5 |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
|
||||
// INPUT VARIABLES
|
||||
input ENUM_TIMEFRAMES inputTimeFrameFractals ;
|
||||
|
||||
|
||||
|
||||
// FRACTAL VARIABLES INITIALIZATION
|
||||
|
||||
input int leftPeriod;
|
||||
input int rightPeriod;
|
||||
input int weekPeriodToInitialize;
|
||||
input int initFractalsPeriod ;
|
||||
int lowFractalIndex ;
|
||||
int highFractalIndex ;
|
||||
|
||||
|
||||
|
||||
|
||||
// GUI CLASSES INCLUDES
|
||||
#include "ZoneContainer.mqh"
|
||||
#include "GraphicalObjectsManager.mqh"
|
||||
#include "ObjectConfirmationUnit.mqh"
|
||||
#include "TempObjectAttributes.mqh"
|
||||
|
||||
|
||||
// DATA STRUCTURE CLASSES INCLUDES
|
||||
#include "Zone.mqh"
|
||||
#include "LowFractal.mqh"
|
||||
#include "HighFractal.mqh"
|
||||
#include "LowFractalContainer.mqh"
|
||||
#include "HighFractalContainer.mqh"
|
||||
|
||||
|
||||
// ALGORITHM CLASSES INCLUDES
|
||||
|
||||
#include "NewCandleDetector.mqh"
|
||||
|
||||
// LIBRARIES INCLUDES
|
||||
#include <library_functions.mqh>
|
||||
|
||||
|
||||
// GUI CLASSES INITIALIZATION
|
||||
GraphicalObjectsManager* objectsManager = new GraphicalObjectsManager();
|
||||
ObjectConfirmationUnit* objectConfUnit = new ObjectConfirmationUnit();
|
||||
TempObjectAttributes* tempObjectAttr = new TempObjectAttributes();
|
||||
|
||||
|
||||
// CONTAINERS INITIALIZATION
|
||||
ZoneContainer zoneContainer ;
|
||||
LowFractalContainer* lowsContainer = new LowFractalContainer(inputTimeFrameFractals) ;
|
||||
|
||||
HighFractalContainer* highsContainer = new HighFractalContainer(inputTimeFrameFractals) ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// GENERAL CHART VARIABLES INITIALIZATION
|
||||
bool initialized = false ;
|
||||
bool firstCandleAfterStart = true ;
|
||||
|
||||
|
||||
// NEW CANDLE CLASSES INITIALIZATION
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
/*NewCandleDetector* newCandleDetectorM1 = new NewCandleDetector("PERIOD_M1");
|
||||
NewCandleDetector* newCandleDetectorM5 = new NewCandleDetector("PERIOD_M5");
|
||||
NewCandleDetector* newCandleDetectorM15 = new NewCandleDetector("PERIOD_M15");
|
||||
NewCandleDetector* newCandleDetectorM30 = new NewCandleDetector("PERIOD_M30");
|
||||
NewCandleDetector* newCandleDetectorH1 = new NewCandleDetector("PERIOD_H1");
|
||||
NewCandleDetector* newCandleDetectorH4 = new NewCandleDetector("PERIOD_H4");
|
||||
NewCandleDetector* newCandleDetectorD1 = new NewCandleDetector("PERIOD_D1"); */
|
||||
|
||||
|
||||
|
||||
// LIVE FORMING FRACTALS HANDLER CLASS
|
||||
NewCandleDetector* newCandleDetectorLive ;
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
//--- create timer
|
||||
EventSetTimer(60);
|
||||
//Print("the ask is: " + SymbolInfoDouble(_Symbol, SYMBOL_ASK));
|
||||
|
||||
// THIS IS FOR SETTING THE NEW CANDLE DETECTOR TIMEFRAME FOR THE LIVE FRACTALS . (IN ORDER TO KNOW WHICH TIMEFRAME OF THE LIVE FRACTALS TO TAKE)
|
||||
|
||||
if(inputTimeFrameFractals == PERIOD_M1)
|
||||
{
|
||||
|
||||
newCandleDetectorLive = new NewCandleDetector("PERIOD_M1");
|
||||
|
||||
}
|
||||
else
|
||||
if(inputTimeFrameFractals == PERIOD_M5)
|
||||
{
|
||||
|
||||
newCandleDetectorLive = new NewCandleDetector("PERIOD_M5");
|
||||
}
|
||||
else
|
||||
if(inputTimeFrameFractals == PERIOD_M15)
|
||||
{
|
||||
newCandleDetectorLive = new NewCandleDetector("PERIOD_M15");
|
||||
|
||||
}
|
||||
else
|
||||
if(inputTimeFrameFractals == PERIOD_M30)
|
||||
{
|
||||
|
||||
newCandleDetectorLive = new NewCandleDetector("PERIOD_M30");
|
||||
}
|
||||
else
|
||||
if(inputTimeFrameFractals == PERIOD_H1)
|
||||
{
|
||||
newCandleDetectorLive = new NewCandleDetector("PERIOD_H1");
|
||||
|
||||
}
|
||||
else
|
||||
if(inputTimeFrameFractals == PERIOD_H4)
|
||||
{
|
||||
newCandleDetectorLive = new NewCandleDetector("PERIOD_H4");
|
||||
|
||||
}
|
||||
else
|
||||
if(inputTimeFrameFractals == PERIOD_D1)
|
||||
{
|
||||
newCandleDetectorLive = new NewCandleDetector("PERIOD_D1");
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(initialized == false)
|
||||
{
|
||||
Print("Shark Initialized successfully on " + Symbol());
|
||||
|
||||
// ADD THE BUTTONS TO THE SCREEN
|
||||
objectsManager.addZoneButton();
|
||||
objectsManager.addConfirmButton();
|
||||
objectsManager.addDeleteButton();
|
||||
objectsManager.addExitExperAdvisorButton();
|
||||
objectsManager.addPrintFractalsButton();
|
||||
objectsManager.addPrintZonesButton();
|
||||
|
||||
// INIT FRACTAL VARIABLES
|
||||
lowFractalIndex = rightPeriod+1 ; // this is used for the fractals
|
||||
highFractalIndex = rightPeriod+1; // this is used for the fractals
|
||||
initLowFractalsFromIndex(initFractalsPeriod,inputTimeFrameFractals);
|
||||
initHighFractalsFromIndex(initFractalsPeriod,inputTimeFrameFractals);
|
||||
|
||||
// INITIALIZATION FLAG
|
||||
initialized = true ;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//---
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- destroy timer
|
||||
/*Print("Low Fractals:");
|
||||
lowsContainer.printLowFractals();
|
||||
Print(" ");
|
||||
Print("High Fractals:");
|
||||
highsContainer.printhighFractals();
|
||||
Print(" "); */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
EventKillTimer();
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//---
|
||||
|
||||
|
||||
|
||||
if(newCandleDetectorLive.isNewCandle())
|
||||
{
|
||||
handleLowFractals(inputTimeFrameFractals); // scans low fractals that are forming and adds them to the container
|
||||
handleHighFractals(inputTimeFrameFractals); // scans high fractals that are forming and adds them to the container
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Timer function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTimer()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Trade function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTrade()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TradeTransaction function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTradeTransaction(const MqlTradeTransaction& trans,
|
||||
const MqlTradeRequest& request,
|
||||
const MqlTradeResult& result)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Tester function |
|
||||
//+------------------------------------------------------------------+
|
||||
double OnTester()
|
||||
{
|
||||
//---
|
||||
double ret=0.0;
|
||||
//---
|
||||
|
||||
//---
|
||||
return(ret);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterInit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterInit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterPass function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterPass()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterDeinit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterDeinit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnChartEvent(const int id,
|
||||
const long &lparam,
|
||||
const double &dparam,
|
||||
const string &sparam)
|
||||
{
|
||||
//---
|
||||
//--- left-clicking on a chart
|
||||
|
||||
switch(id)
|
||||
{
|
||||
|
||||
case CHARTEVENT_CLICK:
|
||||
{
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//--- clicking on a graphical object
|
||||
case CHARTEVENT_OBJECT_CLICK:
|
||||
{
|
||||
if(sparam == "ZONE_ADD_BTN")
|
||||
{
|
||||
|
||||
if(objectConfUnit.getWaitingStatus() == false) // THIS IS TO MAKE SURE THERE IS NO OTHER OBJECT SELECTED
|
||||
{
|
||||
|
||||
// create a rectangle with a unique name
|
||||
int currentIdCounter = zoneContainer.getZonesIdCounter();
|
||||
objectsManager.drawRectangle(currentIdCounter); // create a rectangle . set its name to be the current zonesIdCounter (and that would be the id of this current zone )
|
||||
objectConfUnit.setWaitingStatus(true);
|
||||
objectConfUnit.setObjectType("OBJ_RECTANGLE");
|
||||
objectConfUnit.setConfirmationObjectId(currentIdCounter);
|
||||
zoneContainer.incrementZonesIdCounter();
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Print("Failed to Add a new Object, Make sure to confirm the previous object first! .");
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
if(sparam == "CONFIRM_BTN")
|
||||
{
|
||||
|
||||
if(objectConfUnit.getWaitingStatus() == true) // THIS IS TO MAKE SURE THAT THERE IS SOMETHING SELECTED TO BE CONFIRMED
|
||||
{
|
||||
|
||||
|
||||
if(objectConfUnit.getObjectType() == "OBJ_RECTANGLE") // CASE OF ZONE
|
||||
{
|
||||
|
||||
if(zoneContainer.getZoneIndex(objectConfUnit.getConfirmationObjectId()) != -1) // means the zone already in the data structure, in this case we just need to update it
|
||||
{
|
||||
|
||||
// update the zone attributes
|
||||
// zoneContainer.UpdateZone(int id);
|
||||
Zone* tempZone = new Zone();
|
||||
|
||||
tempZone.setHigherEdgePrice(tempObjectAttr.getHigherEdgePrice()) ;
|
||||
tempZone.setLowerEdgePrice(tempObjectAttr.getLowerEdgePrice());
|
||||
tempZone.setLeftEdge(tempObjectAttr.getLeftEdgeTime());
|
||||
tempZone.setRightEdge(tempObjectAttr.getRightEdgeTime());
|
||||
tempZone.setTimeFrame(tempObjectAttr.getTimeFrame());
|
||||
|
||||
string idOfOriginalZone = objectConfUnit.getConfirmationObjectId();
|
||||
// no need to set the ID here because the ID belongs to the original zone and not this new temp one (this is just a temporary zone to check if the adjustment is valid or no)
|
||||
|
||||
if(zoneContainer.updateZone(tempZone, idOfOriginalZone) ==1)
|
||||
{
|
||||
// in this case we successfully updated the zone
|
||||
|
||||
Print("Updated the object:" +
|
||||
"\n ID: " + objectConfUnit.getConfirmationObjectId() +
|
||||
"\n Type: " + objectConfUnit.getObjectType() +
|
||||
"\n Asset: " + tempObjectAttr.getSymbol() +
|
||||
"\n Time Frame:" + tempObjectAttr.getTimeFrame() +
|
||||
"\n Higher Edge Price: " + tempObjectAttr.getHigherEdgePrice() +
|
||||
"\n Lower Edge Price: " + tempObjectAttr.getLowerEdgePrice() +
|
||||
"\n Left Edge Date: " + tempObjectAttr.getLeftEdgeTime() +
|
||||
"\n Right Edge Date: " + tempObjectAttr.getRightEdgeTime()
|
||||
);
|
||||
|
||||
delete tempZone;
|
||||
if(ObjectSetInteger(_Symbol,objectConfUnit.getConfirmationObjectId(),OBJPROP_SELECTED,false) == true) // this is to unselect the object once we finish using it
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to unselect the object. Error: " + GetLastError());
|
||||
}
|
||||
|
||||
// THIS IS TO CLEAN THE objectConfUnit
|
||||
objectConfUnit.setWaitingStatus(false);
|
||||
ChartRedraw();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Print("Failed to update the zone, please reposition it");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else // means the zone is new so we need to add it
|
||||
{
|
||||
Zone* newZone = new Zone() ;
|
||||
newZone.setHigherEdgePrice(tempObjectAttr.getHigherEdgePrice());
|
||||
newZone.setLowerEdgePrice(tempObjectAttr.getLowerEdgePrice());
|
||||
newZone.setLeftEdge(tempObjectAttr.getLeftEdgeTime());
|
||||
newZone.setRightEdge(tempObjectAttr.getRightEdgeTime());
|
||||
newZone.setId(objectConfUnit.getConfirmationObjectId());
|
||||
newZone.setTimeFrame(tempObjectAttr.getTimeFrame());
|
||||
if(tempObjectAttr.getHigherEdgePrice() < SymbolInfoDouble(_Symbol, SYMBOL_ASK) ){ // means its a support zone
|
||||
newZone.setType("TYPE_SUPPORT");
|
||||
}
|
||||
if(tempObjectAttr.getLowerEdgePrice() > SymbolInfoDouble(_Symbol, SYMBOL_ASK)){ // means its a resistance zone
|
||||
newZone.setType("TYPE_RESISTANCE");
|
||||
}
|
||||
// add the zone to the data structure
|
||||
if(zoneContainer.addZone(newZone) == 1)
|
||||
{
|
||||
zoneContainer.findOrUpdatePivotEdges(); // update the pivot edges
|
||||
Print("Added the object:" +
|
||||
"\n ID: " + objectConfUnit.getConfirmationObjectId() +
|
||||
"\n Type: " + objectConfUnit.getObjectType() +
|
||||
"\n Asset: " + tempObjectAttr.getSymbol() +
|
||||
"\n Time Frame:" + tempObjectAttr.getTimeFrame() +
|
||||
"\n Higher Edge Price: " + tempObjectAttr.getHigherEdgePrice() +
|
||||
"\n Lower Edge Price: " + tempObjectAttr.getLowerEdgePrice() +
|
||||
"\n Left Edge Date: " + tempObjectAttr.getLeftEdgeTime() +
|
||||
"\n Right Edge Date: " + tempObjectAttr.getRightEdgeTime()
|
||||
);
|
||||
|
||||
|
||||
|
||||
if(ObjectSetInteger(_Symbol,objectConfUnit.getConfirmationObjectId(),OBJPROP_SELECTED,false) == true) // this is to unselect the object once we finish using it
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to unselect the object. Error: " + GetLastError());
|
||||
}
|
||||
|
||||
// THIS IS TO CLEAN THE objectConfUnit
|
||||
objectConfUnit.setWaitingStatus(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to add the zone, Error: 2 or more zones are crossing");
|
||||
}
|
||||
|
||||
ChartRedraw();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
if(objectConfUnit.getObjectType() == "OBJ_TRENDLINE") // CASE OF TRENDLINE
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Print("Cannot confirm, Please select an object first !");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
if(sparam == "DELETE_BTN")
|
||||
{
|
||||
if(objectConfUnit.getWaitingStatus() == true) // THIS IS TO MAKE SURE THAT THERE IS SOMETHING SELECTED TO BE DELETED
|
||||
{
|
||||
if(ObjectDelete(_Symbol,objectConfUnit.getConfirmationObjectId()))
|
||||
{
|
||||
if(zoneContainer.deleteZone(objectConfUnit.getConfirmationObjectId()) == 1)
|
||||
{ // delete from data structure
|
||||
zoneContainer.findOrUpdatePivotEdges();
|
||||
Print("Deleted the object: " +
|
||||
"\n Type: " + objectConfUnit.getObjectType() +
|
||||
"\n ID: " + objectConfUnit.getConfirmationObjectId());
|
||||
|
||||
objectConfUnit.setWaitingStatus(false);
|
||||
objectConfUnit.setObjectType("NO_OBJECT");
|
||||
objectConfUnit.setConfirmationObjectId(-2);
|
||||
|
||||
ChartRedraw();
|
||||
}
|
||||
else{
|
||||
objectConfUnit.setWaitingStatus(false);
|
||||
objectConfUnit.setObjectType("NO_OBJECT");
|
||||
objectConfUnit.setConfirmationObjectId(-2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Print("Cannot delete, Please select an object first !");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
if(sparam == "EXIT_BTN")
|
||||
{
|
||||
delete objectsManager ;
|
||||
delete objectConfUnit;
|
||||
delete tempObjectAttr;
|
||||
delete lowsContainer;
|
||||
delete highsContainer;
|
||||
|
||||
delete newCandleDetectorLive;
|
||||
zoneContainer.freeZonesSortedArray();
|
||||
/*delete newCandleDetectorD1;
|
||||
delete newCandleDetectorM5;
|
||||
delete newCandleDetectorM30;
|
||||
delete newCandleDetectorM15;
|
||||
delete newCandleDetectorM1;
|
||||
delete newCandleDetectorH4;
|
||||
delete newCandleDetectorH1; */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ExpertRemove();
|
||||
}
|
||||
else
|
||||
if(sparam == "PRINT_FRACTAL_BTN")
|
||||
{
|
||||
Print("Low Fractals:");
|
||||
lowsContainer.printLowFractals();
|
||||
Print("High Fractals:");
|
||||
highsContainer.printHighFractals();
|
||||
}
|
||||
|
||||
else
|
||||
if(sparam == "PRINT_ZONES_BTN")
|
||||
{
|
||||
|
||||
zoneContainer.printZonesSortedArray();
|
||||
}
|
||||
else // THIS is the case were we click on any object except for the 'Add Zone' and 'Confirm Object' Buttons
|
||||
{
|
||||
|
||||
if(objectConfUnit.getWaitingStatus() == true) // THIS IS TO MAKE SURE THERE IS NO OTHER OBJECT SELECTED
|
||||
{
|
||||
Print("Cannot select the object clicked, Make sure to confirm a previous selected object first !");
|
||||
}
|
||||
else
|
||||
{
|
||||
ObjectSetInteger(_Symbol,sparam,OBJPROP_SELECTED,true);
|
||||
|
||||
if(ObjectGetInteger(_Symbol,sparam,OBJPROP_TYPE,0) == OBJ_RECTANGLE)
|
||||
{
|
||||
Print("Selected the object:" +
|
||||
"\n Type: OBJ_RECTANGLE" +
|
||||
"\n ID: " + sparam);
|
||||
objectConfUnit.setWaitingStatus(true) ;
|
||||
objectConfUnit.setConfirmationObjectId(StringToInteger(sparam));
|
||||
objectConfUnit.setObjectType("OBJ_RECTANGLE");
|
||||
ChartRedraw();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
//--- object moved or anchor point coordinates changed
|
||||
case CHARTEVENT_OBJECT_DRAG:
|
||||
{
|
||||
|
||||
double _higherEdgePrice = ObjectGetDouble(_Symbol,sparam,OBJPROP_PRICE,1);
|
||||
double _lowerEdgePrice = ObjectGetDouble(_Symbol,sparam,OBJPROP_PRICE,0);
|
||||
|
||||
datetime _leftEdgeTime = (datetime)ObjectGetInteger(_Symbol,sparam,OBJPROP_TIME,0);
|
||||
datetime _rightEdgeTime = (datetime)ObjectGetInteger(_Symbol,sparam,OBJPROP_TIME,1);
|
||||
|
||||
if(_higherEdgePrice < _lowerEdgePrice) // this is the case were the user flips the rectangle while adjusting it.
|
||||
{
|
||||
tempObjectAttr.setHigherEdgePrice(_lowerEdgePrice);
|
||||
tempObjectAttr.setLowerEdgePrice(_higherEdgePrice);
|
||||
}
|
||||
else
|
||||
{
|
||||
tempObjectAttr.setHigherEdgePrice(_higherEdgePrice);
|
||||
tempObjectAttr.setLowerEdgePrice(_lowerEdgePrice);
|
||||
}
|
||||
|
||||
tempObjectAttr.setLeftEdgeTime(_leftEdgeTime);
|
||||
tempObjectAttr.setRightEdgeTime(_rightEdgeTime);
|
||||
tempObjectAttr.setSymbol();
|
||||
tempObjectAttr.setTimeFrame(getChartTimeFrameInString());
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| BookEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnBookEvent(const string &symbol)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void initLowFractalsFromIndex(int _index,ENUM_TIMEFRAMES timeFramePeriod)
|
||||
{
|
||||
|
||||
for(int i=_index ; i> rightPeriod ; i--)
|
||||
{
|
||||
|
||||
bool accessDeniedLows = false ; // variable for dealing with equal consecutive fractals
|
||||
|
||||
|
||||
|
||||
if(isLowFractalByIndex(i,leftPeriod,rightPeriod,timeFramePeriod) == true)
|
||||
{
|
||||
|
||||
if(lowsContainer.getFreeIndex() > 0)
|
||||
{
|
||||
|
||||
if(iLow(Symbol(),timeFramePeriod,i) == lowsContainer.getLowFractal(lowsContainer.getFreeIndex()-1).getPrice()) // if low fractal is equal to the previous low fractal
|
||||
{
|
||||
if(lowsContainer.getLowFractal(lowsContainer.getFreeIndex()-1).getDistance() - i < 2*rightPeriod) // if the 2 lows are inside the range of 2 times of right period
|
||||
{
|
||||
accessDeniedLows = true ;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(accessDeniedLows == false)
|
||||
{
|
||||
|
||||
|
||||
LowFractal* currentFractal = new LowFractal(iLow(Symbol(),timeFramePeriod,i),leftPeriod,rightPeriod,TimeCurrent(),timeFramePeriod);
|
||||
currentFractal.setDate(iTime(Symbol(),timeFramePeriod,i));
|
||||
currentFractal.setDistance(i);
|
||||
int NumberOfCandle = i-1;
|
||||
string NumberOfCandleText = IntegerToString(NumberOfCandle);
|
||||
currentFractal.setArrowObjName(NumberOfCandleText);
|
||||
lowsContainer.addLowFractal(currentFractal);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void initHighFractalsFromIndex(int _index,ENUM_TIMEFRAMES timeFramePeriod)
|
||||
{
|
||||
|
||||
for(int i=_index ; i> rightPeriod ; i--)
|
||||
{
|
||||
|
||||
bool accessDeniedHighs = false ; // variable for dealing with equal consecutive fractals
|
||||
|
||||
|
||||
|
||||
if(isHighFractalByIndex(i,leftPeriod,rightPeriod,timeFramePeriod) == true)
|
||||
{
|
||||
|
||||
if(highsContainer.getFreeIndex() > 0)
|
||||
{
|
||||
|
||||
if(iHigh(Symbol(),timeFramePeriod,i) == highsContainer.getHighFractal(highsContainer.getFreeIndex()-1).getPrice()) // if high fractal is equal to the previous high fractal
|
||||
{
|
||||
|
||||
if(highsContainer.getHighFractal(highsContainer.getFreeIndex()-1).getDistance() - i < 2*rightPeriod) // if the 2 highs are inside the range of 2 times of right period
|
||||
{
|
||||
|
||||
accessDeniedHighs = true ;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(accessDeniedHighs == false)
|
||||
{
|
||||
|
||||
|
||||
HighFractal* currentFractal = new HighFractal(iHigh(Symbol(),timeFramePeriod,i),leftPeriod,rightPeriod,TimeCurrent(),timeFramePeriod);
|
||||
currentFractal.setDate(iTime(Symbol(),timeFramePeriod,i));
|
||||
currentFractal.setDistance(i);
|
||||
int NumberOfCandle = i-1;
|
||||
string NumberOfCandleText = IntegerToString(NumberOfCandle);
|
||||
currentFractal.setArrowObjName(NumberOfCandleText);
|
||||
highsContainer.addHighFractal(currentFractal);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void handleLowFractals(ENUM_TIMEFRAMES tf)
|
||||
{
|
||||
|
||||
bool accessDeniedLows = false ; // variable for dealing with equal consecutive fractals if its true, then the current fractal will not be added
|
||||
|
||||
for(int x=0 ; x<lowsContainer.getFreeIndex(); x++)
|
||||
{
|
||||
|
||||
lowsContainer.getLowFractal(x).updateDistance(); // update the distance for every fractal in the container
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(isLowFractalByIndex(lowFractalIndex,leftPeriod,rightPeriod,tf) == true)
|
||||
{
|
||||
|
||||
if(lowsContainer.getFreeIndex() > 0)
|
||||
{
|
||||
|
||||
if(iLow(Symbol(),tf,lowFractalIndex) == lowsContainer.getLowFractal(lowsContainer.getFreeIndex()-1).getPrice()) // if low fractal is equal to the previous low fractal
|
||||
{
|
||||
|
||||
if(lowsContainer.getLowFractal(lowsContainer.getFreeIndex()-1).getDistance() <= 2*rightPeriod) // if the 2 lows are inside the range of 2 times of right period
|
||||
{
|
||||
|
||||
accessDeniedLows = true ;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(accessDeniedLows == false)
|
||||
{
|
||||
|
||||
LowFractal* currentFractal = new LowFractal(iLow(Symbol(),tf,lowFractalIndex),leftPeriod,rightPeriod,TimeCurrent(),tf);
|
||||
|
||||
int NumberOfCandle = Bars(Symbol(),tf);
|
||||
string NumberOfCandleText = IntegerToString(NumberOfCandle);
|
||||
currentFractal.setArrowObjName(NumberOfCandleText);
|
||||
lowsContainer.addLowFractal(currentFractal);
|
||||
Print("added a new low fractal !");
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void handleHighFractals(ENUM_TIMEFRAMES tf)
|
||||
{
|
||||
|
||||
|
||||
bool accessDeniedHighs = false ; // variable for dealing with equal consecutive fractals
|
||||
|
||||
for(int x=0 ; x<highsContainer.getFreeIndex(); x++)
|
||||
{
|
||||
|
||||
highsContainer.getHighFractal(x).updateDistance(); // update the distance for every fractal in the container
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(isHighFractalByIndex(highFractalIndex,leftPeriod,rightPeriod,tf) == true)
|
||||
{
|
||||
|
||||
if(highsContainer.getFreeIndex() > 0)
|
||||
{
|
||||
|
||||
if(iHigh(Symbol(),tf,highFractalIndex) == highsContainer.getHighFractal(highsContainer.getFreeIndex()-1).getPrice()) // if high fractal is equal to the previous high fractal
|
||||
{
|
||||
if(highsContainer.getHighFractal(highsContainer.getFreeIndex()-1).getDistance() <= 2*rightPeriod) // if the 2 highs are inside the range of 2 times of right period
|
||||
{
|
||||
accessDeniedHighs = true ;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(accessDeniedHighs == false)
|
||||
{
|
||||
|
||||
|
||||
HighFractal* currentFractal = new HighFractal(iHigh(Symbol(),tf,highFractalIndex),leftPeriod,rightPeriod,TimeCurrent(),tf);
|
||||
|
||||
int NumberOfCandle = Bars(Symbol(),tf);
|
||||
string NumberOfCandleText = IntegerToString(NumberOfCandle);
|
||||
currentFractal.setArrowObjName(NumberOfCandleText);
|
||||
highsContainer.addHighFractal(currentFractal);
|
||||
Print("added a new high fractal !");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
+1191
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,40 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| TempLineObjectAttributes.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
class TempLineObjectAttributes
|
||||
{
|
||||
private:
|
||||
|
||||
string id ;
|
||||
double price ;
|
||||
|
||||
public:
|
||||
TempLineObjectAttributes();
|
||||
~TempLineObjectAttributes();
|
||||
|
||||
// GETTERS
|
||||
string getId(){return id;}
|
||||
double getPrice(){return price ;}
|
||||
|
||||
// SETTERS
|
||||
void setId(string _id){id =_id ;}
|
||||
void setPrice(double _price){price = _price ;}
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
TempLineObjectAttributes::TempLineObjectAttributes()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
TempLineObjectAttributes::~TempLineObjectAttributes()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,81 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| TempObjectAttributes.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
class TempObjectAttributes
|
||||
{
|
||||
private:
|
||||
// ATTRIBUTES FOR A ZONE
|
||||
string assetName;
|
||||
string timeFrame ;
|
||||
double higherEdgePrice ;
|
||||
double lowerEdgePrice ;
|
||||
datetime leftEdgeTime ;
|
||||
datetime rightEdgeTime;
|
||||
|
||||
|
||||
// ATTRIBUTES FOR TRENDLINE
|
||||
|
||||
|
||||
|
||||
// ATTRIBUTES FOR DAILY LINE
|
||||
|
||||
|
||||
|
||||
// ATTRIBUTES FOR IMBALANCE
|
||||
|
||||
|
||||
|
||||
// ATTRIBUTES FOR FIBONACCI LEVEL
|
||||
|
||||
|
||||
|
||||
|
||||
public:
|
||||
TempObjectAttributes();
|
||||
~TempObjectAttributes();
|
||||
|
||||
// GETTERS FOR ZONE
|
||||
double getHigherEdgePrice(){return higherEdgePrice;}
|
||||
double getLowerEdgePrice(){return lowerEdgePrice;}
|
||||
datetime getLeftEdgeTime(){return leftEdgeTime ;}
|
||||
datetime getRightEdgeTime(){return rightEdgeTime;}
|
||||
string getSymbol(){return assetName;}
|
||||
string getTimeFrame(){return timeFrame;}
|
||||
|
||||
// SETTERS FOR ZONE
|
||||
void setHigherEdgePrice(double _higherEdgePrice){higherEdgePrice = _higherEdgePrice;}
|
||||
void setLowerEdgePrice(double _lowerEdgePrice){lowerEdgePrice = _lowerEdgePrice;}
|
||||
void setLeftEdgeTime(datetime _leftEdgeTime){leftEdgeTime = _leftEdgeTime;}
|
||||
void setRightEdgeTime(datetime _rightEdgeTime){rightEdgeTime = _rightEdgeTime;}
|
||||
void setSymbol(){assetName = Symbol();}
|
||||
void setTimeFrame(string _timeframe){timeFrame = _timeframe;}
|
||||
// OTHER ZONE FUNCTIONS
|
||||
|
||||
void cleanAttributesZone(){higherEdgePrice = -1;
|
||||
lowerEdgePrice = -1;
|
||||
leftEdgeTime = 0;
|
||||
rightEdgeTime = 0;}
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
TempObjectAttributes::TempObjectAttributes()
|
||||
{
|
||||
|
||||
higherEdgePrice = -1;
|
||||
lowerEdgePrice = -1;
|
||||
leftEdgeTime = 0;
|
||||
rightEdgeTime = 0;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
TempObjectAttributes::~TempObjectAttributes()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,601 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Tiger.mq5 |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include "NewCandleDetector.mqh"
|
||||
#include "GraphicalObjectsManager.mqh"
|
||||
#include "Zone.mqh"
|
||||
#include "ZoneContainer.mqh"
|
||||
|
||||
#include "MarketObserver.mqh"
|
||||
#include "BuyEntryManager.mqh"
|
||||
#include "LotSizeCalculator.mqh"
|
||||
input double rangeDistance ;
|
||||
input double resistanceExtendAboveCandle;
|
||||
input double supportExtendBelowCandle ;
|
||||
input double stopLossLimit ;
|
||||
double input riskInDollars ;
|
||||
double input netTakeProfit ;
|
||||
bool input allowSecondChanceStopLoss ;
|
||||
double input bottomWickSize ;
|
||||
double input smallBottomWickSize ;
|
||||
double input buyStopPipsTrigger ;
|
||||
bool input MOD_CLEAN = false ;
|
||||
|
||||
|
||||
bool waitingForBottomWickToForm = false ;
|
||||
bool waitingForSmallBottomWickToForm = false ;
|
||||
bool buyStopValid = false ;
|
||||
bool closedPartialOnNegativeDirection = false ;
|
||||
bool securedTenPips = false ;
|
||||
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
|
||||
CTrade tradeTiger ;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
// GUI CLASSES INITIALIZATION
|
||||
GraphicalObjectsManager* objectsManager = new GraphicalObjectsManager();
|
||||
|
||||
// CONTAINERS INITIALIZATION
|
||||
ZoneContainer* zoneContainer = new ZoneContainer() ;
|
||||
|
||||
|
||||
|
||||
|
||||
// ALGORITHM CLASSES INITIALIZATION
|
||||
MarketObserver* marketObserver = new MarketObserver(zoneContainer);
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
NewCandleDetector newCandleDetector("PERIOD_M30");
|
||||
BuyEntryManager buyEntryMan ;
|
||||
LotSizeCalculator lotSizeCalc ;
|
||||
|
||||
|
||||
Zone* temporaryRestestSupportZone = new Zone();
|
||||
int OnInit()
|
||||
{
|
||||
//--- create timer
|
||||
EventSetTimer(60);
|
||||
iClose(_Symbol,PERIOD_M15,5);
|
||||
iClose(_Symbol,PERIOD_H1,5);
|
||||
|
||||
/*datetime d1=D'2023.09.01 00:00:00'; // Year Month Day Hours Minutes Seconds
|
||||
Print("the dateTime is: " + d1);
|
||||
|
||||
Zone* newZone = new Zone() ;
|
||||
newZone.setHigherEdgePrice(1930);
|
||||
newZone.setLowerEdgePrice(1925);
|
||||
newZone.setLeftEdge(iTime(_Symbol,PERIOD_CURRENT,2));
|
||||
newZone.setRightEdge(d1);
|
||||
newZone.setId("1");
|
||||
newZone.setTimeFrame("PERIOD_M30");
|
||||
|
||||
|
||||
zoneContainer.addZone(newZone);
|
||||
objectsManager.drawRectangleInStrategyTester(1,iTime(_Symbol,PERIOD_CURRENT,2),d1,1930,1925);
|
||||
zoneContainer.printZonesSortedArray(); */
|
||||
|
||||
|
||||
//---
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- destroy timer
|
||||
EventKillTimer();
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//---
|
||||
|
||||
|
||||
if(securedTenPips == false ){
|
||||
secureTenPips(0.3);
|
||||
}
|
||||
|
||||
if(waitingForBottomWickToForm){
|
||||
if(iClose(_Symbol,PERIOD_CURRENT,1) - SymbolInfoDouble(_Symbol, SYMBOL_BID) >= bottomWickSize){
|
||||
|
||||
waitingForBottomWickToForm = false ;
|
||||
Print("Bottom Wick in length of at least " + bottomWickSize + " was formed !");
|
||||
buyStopValid = true ;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if(buyStopValid){
|
||||
if( SymbolInfoDouble(_Symbol, SYMBOL_ASK) > iHigh(_Symbol,PERIOD_CURRENT,1) + buyStopPipsTrigger){ // here we take a buy entry based on break and retest wick. the Algo will first try to put the stop loss under the low of the temporary support zone
|
||||
// if that stop loss was too high , then it will put it under the low of the wick that was recently made. (the wick should be at least bottomWickSize which is currently 1)
|
||||
|
||||
double stopLossUnderTemporarySupportZone = temporaryRestestSupportZone.getLowerEdge() - 0.5 ; // under the temporary support zone
|
||||
double stopLossUnderWick = iLow(_Symbol,PERIOD_CURRENT,0) - 0.5; // the low of the current candle
|
||||
|
||||
if(!((SymbolInfoDouble(_Symbol, SYMBOL_ASK) - stopLossUnderTemporarySupportZone) > stopLossLimit)){ // on this case a wick was formed price starts to break the previous candle high, im taking a buy
|
||||
//and im putting the stop loss below the whole zone (which is support now)
|
||||
double lotsToEnter = lotSizeCalc.calculateLotSize(riskInDollars,stopLossUnderTemporarySupportZone);
|
||||
buyEntryMan.takeBuyTradeTiger(lotsToEnter,stopLossUnderTemporarySupportZone,2);
|
||||
closedPartialOnNegativeDirection = false ;
|
||||
securedTenPips = false ;
|
||||
buyStopValid = false ;
|
||||
Print("Took a wick retest buy type 1");
|
||||
|
||||
|
||||
}
|
||||
else if(!((SymbolInfoDouble(_Symbol, SYMBOL_ASK) - stopLossUnderWick) > stopLossLimit)){ // on this case a wick was formed price starts to break the previous candle high, im taking a buy
|
||||
//and im putting the stop loss below the wick (which is at least bottomWickSize)
|
||||
|
||||
double lotsToEnter = lotSizeCalc.calculateLotSize(riskInDollars,stopLossUnderWick);
|
||||
buyEntryMan.takeBuyTradeTiger(lotsToEnter,stopLossUnderWick,2);
|
||||
closedPartialOnNegativeDirection = false ;
|
||||
securedTenPips = false ;
|
||||
buyStopValid = false ;
|
||||
Print("Took a wick retest buy type 2");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(newCandleDetector.isNewCandle())
|
||||
{
|
||||
|
||||
|
||||
if(iClose(_Symbol,PERIOD_CURRENT,1) < iOpen(_Symbol,PERIOD_CURRENT,1) && closedPartialOnNegativeDirection == false){ // if the m30 candle closed bearish
|
||||
closePartialsOfAllTrades(0.5);
|
||||
closedPartialOnNegativeDirection = true ;
|
||||
}
|
||||
|
||||
|
||||
buyStopValid = false ;
|
||||
waitingForBottomWickToForm = false ;
|
||||
bool finishedDeleting = false ;
|
||||
MqlDateTime mqldt ;
|
||||
datetime currTime = TimeCurrent(mqldt);
|
||||
|
||||
|
||||
|
||||
if(candleClosedBelowRetestZone(PERIOD_CURRENT)){
|
||||
temporaryRestestSupportZone.setType("TYPE_INVALID");
|
||||
deleteZoneGuiOnly("999");
|
||||
|
||||
}
|
||||
|
||||
if(zoneContainer.getNumberOfActiveZones() != 0) // if there are zones found
|
||||
{
|
||||
if(marketObserver.candleClosedAboveResistanceByIndex(0,PERIOD_CURRENT)) // check if candle closed above the zone
|
||||
{
|
||||
|
||||
|
||||
datetime _leftEdgeRestestZone = iTime(_Symbol,PERIOD_CURRENT,4);
|
||||
datetime _rightEdgeRetestZone = D'2023.11.01 00:00:00';
|
||||
|
||||
|
||||
|
||||
while(!finishedDeleting && zoneContainer.getNumberOfActiveZones() != 0) // this while is used in the case of a candle closing above more than 1 zone at once
|
||||
{
|
||||
/* temporaryRestestSupportZone.setHigherEdgePrice(zoneContainer.getZoneByIndex(0).getHigherEdge());
|
||||
temporaryRestestSupportZone.setLowerEdgePrice(zoneContainer.getZoneByIndex(0).getLowerEdge());
|
||||
temporaryRestestSupportZone.setLeftEdge(_leftEdgeRestestZone);
|
||||
temporaryRestestSupportZone.setRightEdge(_rightEdgeRetestZone);
|
||||
temporaryRestestSupportZone.setId("999"); // the + "t" stands for temporary and it is made to keep the zones id's unique
|
||||
temporaryRestestSupportZone.setTimeFrame("PERIOD_M30");
|
||||
temporaryRestestSupportZone.setType("TYPE_SUPPORT");
|
||||
deleteZoneWithGUI((zoneContainer.getZoneByIndex(0).getId())); // delete the zone with the GUI */
|
||||
|
||||
if(zoneContainer.getNumberOfActiveZones() != 0 && marketObserver.candleClosedAboveResistanceByIndex(0,PERIOD_CURRENT))
|
||||
{
|
||||
zoneContainer.getZoneByIndex(0).getHigherEdge();
|
||||
temporaryRestestSupportZone.setHigherEdgePrice(zoneContainer.getZoneByIndex(0).getHigherEdge());
|
||||
temporaryRestestSupportZone.setLowerEdgePrice(zoneContainer.getZoneByIndex(0).getLowerEdge());
|
||||
temporaryRestestSupportZone.setLeftEdge(_leftEdgeRestestZone);
|
||||
temporaryRestestSupportZone.setRightEdge(_rightEdgeRetestZone);
|
||||
temporaryRestestSupportZone.setId("999"); // the + "t" stands for temporary and it is made to keep the zones id's unique
|
||||
temporaryRestestSupportZone.setTimeFrame("PERIOD_M30");
|
||||
temporaryRestestSupportZone.setType("TYPE_SUPPORT");
|
||||
deleteZoneWithGUI((zoneContainer.getZoneByIndex(0).getId())); // delete the zone with the GUI
|
||||
}
|
||||
else
|
||||
{
|
||||
finishedDeleting = true ;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int idAsInt = StringToInteger(temporaryRestestSupportZone.getId());
|
||||
|
||||
|
||||
if((mqldt.hour > 13 && mqldt.hour < 22) || (mqldt.hour > 3 && mqldt.hour < 7) || (mqldt.hour > 8 && mqldt.hour < 12) )
|
||||
{
|
||||
|
||||
|
||||
double stopLossPrice = iLow(_Symbol,PERIOD_CURRENT,1);
|
||||
stopLossPrice = stopLossPrice -1;
|
||||
|
||||
double secondChanceStopLossPrice = iLow(_Symbol,PERIOD_M15,1);
|
||||
secondChanceStopLossPrice = secondChanceStopLossPrice -1;
|
||||
|
||||
if(!(SymbolInfoDouble(_Symbol, SYMBOL_ASK) - stopLossPrice > stopLossLimit)) // enter only if the M30 previous candle satisfied the condition of the proper stop loss
|
||||
{
|
||||
//Print("Entered here 2!");
|
||||
double lotsToEnter = lotSizeCalc.calculateLotSize(riskInDollars,stopLossPrice);
|
||||
buyEntryMan.takeBuyTradeTiger(lotsToEnter,stopLossPrice,netTakeProfit);
|
||||
closedPartialOnNegativeDirection = false ;
|
||||
securedTenPips = false ;
|
||||
}
|
||||
else
|
||||
if(!(SymbolInfoDouble(_Symbol, SYMBOL_ASK) - secondChanceStopLossPrice > stopLossLimit) && secondChanceStopLossPrice < temporaryRestestSupportZone.getLowerEdge() - 0.5) // if the M30 candle failed , then try the M15 candle
|
||||
{
|
||||
|
||||
if(allowSecondChanceStopLoss == true)
|
||||
{
|
||||
|
||||
double lotsToEnter = lotSizeCalc.calculateLotSize(riskInDollars,secondChanceStopLossPrice);
|
||||
buyEntryMan.takeBuyTradeTiger(lotsToEnter,secondChanceStopLossPrice,netTakeProfit);
|
||||
closedPartialOnNegativeDirection = false ;
|
||||
securedTenPips = false ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
else // both M30 and M15 candles closed too far from the zone, so im gonna wait for retracement , and support to be built on the zone, or a bottom wick to form
|
||||
{
|
||||
|
||||
objectsManager.drawRectangleInStrategyTester(idAsInt,_leftEdgeRestestZone,_rightEdgeRetestZone,
|
||||
temporaryRestestSupportZone.getHigherEdge(),temporaryRestestSupportZone.getLowerEdge(),clrGray);
|
||||
|
||||
|
||||
waitingForBottomWickToForm = true ;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(candleClosedBullish(PERIOD_M30,2) && candleClosedBearish(PERIOD_M30,1))
|
||||
{
|
||||
|
||||
// create a rectangle with a unique name
|
||||
int currentIdCounter = zoneContainer.getZonesIdCounter();
|
||||
|
||||
|
||||
datetime _leftEdge = iTime(_Symbol,PERIOD_CURRENT,2);
|
||||
datetime _rightEdge = D'2023.11.01 00:00:00';
|
||||
double resistancePrice = iOpen(_Symbol,PERIOD_CURRENT,1);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if((zoneContainer.getNumberOfActiveZones() != 0) && (zoneContainer.getZoneByIndex(0).getLowerEdge() - resistancePrice >= rangeDistance))
|
||||
{
|
||||
|
||||
Zone* newZone = new Zone() ;
|
||||
newZone.setHigherEdgePrice(resistancePrice + resistanceExtendAboveCandle);
|
||||
newZone.setLowerEdgePrice(resistancePrice);
|
||||
newZone.setLeftEdge(_leftEdge);
|
||||
newZone.setRightEdge(_rightEdge);
|
||||
newZone.setId(IntegerToString(currentIdCounter));
|
||||
newZone.setTimeFrame("PERIOD_M30");
|
||||
newZone.setType("TYPE_RESISTANCE");
|
||||
|
||||
|
||||
|
||||
|
||||
zoneContainer.addResistanceZoneTiger(newZone);
|
||||
zoneContainer.incrementZonesIdCounter();
|
||||
|
||||
|
||||
objectsManager.drawRectangleInStrategyTester(currentIdCounter,_leftEdge,_rightEdge,resistancePrice + resistanceExtendAboveCandle,resistancePrice,clrBeige);
|
||||
//Print("Number of active zones is: " + zoneContainer.getNumberOfActiveZones());
|
||||
//zoneContainer.printZonesSortedArray();
|
||||
}
|
||||
|
||||
else if((zoneContainer.getNumberOfActiveZones() != 0) && (zoneContainer.getZoneByIndex(0).getLowerEdge() - resistancePrice < rangeDistance)){
|
||||
double currentHighEdge = resistancePrice + resistanceExtendAboveCandle ; // this is a high edge of a resistance, but its not considered as a zone, because it doesnt have clean range above
|
||||
double currentLowEdge = resistancePrice; // this is a low edge of a resistance, but its not considered as a zone, because it doesnt have clean range above
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
if(zoneContainer.getNumberOfActiveZones() == 0) // this means this is the first zone to add to the data strucutre
|
||||
{
|
||||
|
||||
//Print("Entered here 2");
|
||||
Zone* newZone = new Zone() ;
|
||||
newZone.setHigherEdgePrice(resistancePrice + resistanceExtendAboveCandle);
|
||||
newZone.setLowerEdgePrice(resistancePrice);
|
||||
newZone.setLeftEdge(_leftEdge);
|
||||
newZone.setRightEdge(_rightEdge);
|
||||
newZone.setId(IntegerToString(currentIdCounter));
|
||||
newZone.setTimeFrame("PERIOD_M30");
|
||||
newZone.setType("TYPE_RESISTANCE");
|
||||
|
||||
|
||||
|
||||
zoneContainer.addResistanceZoneTiger(newZone);
|
||||
zoneContainer.incrementZonesIdCounter();
|
||||
|
||||
|
||||
objectsManager.drawRectangleInStrategyTester(currentIdCounter,_leftEdge,_rightEdge,resistancePrice + resistanceExtendAboveCandle,resistancePrice,clrBeige);
|
||||
//zoneContainer.printZonesSortedArray();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
Print("Number of active zones is: " + zoneContainer.getNumberOfActiveZones());
|
||||
Print("Zones are : ");
|
||||
zoneContainer.printZonesSortedArray();
|
||||
}
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Timer function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTimer()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Trade function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTrade()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TradeTransaction function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTradeTransaction(const MqlTradeTransaction& trans,
|
||||
const MqlTradeRequest& request,
|
||||
const MqlTradeResult& result)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Tester function |
|
||||
//+------------------------------------------------------------------+
|
||||
double OnTester()
|
||||
{
|
||||
//---
|
||||
double ret=0.0;
|
||||
//---
|
||||
|
||||
//---
|
||||
return(ret);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterInit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterInit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterPass function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterPass()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterDeinit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterDeinit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnChartEvent(const int id,
|
||||
const long &lparam,
|
||||
const double &dparam,
|
||||
const string &sparam)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| BookEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnBookEvent(const string &symbol)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool resistanceIsFound()
|
||||
{
|
||||
|
||||
//if()
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool candleClosedBullish(ENUM_TIMEFRAMES _timeFrame, int _index)
|
||||
{
|
||||
double candleClose = iClose(_Symbol,_timeFrame,_index);
|
||||
double candleOpen = iOpen(_Symbol,_timeFrame,_index);
|
||||
|
||||
|
||||
if(candleClose >candleOpen) // the candle closed bullish
|
||||
{
|
||||
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool candleClosedBearish(ENUM_TIMEFRAMES _timeFrame,int _index)
|
||||
{
|
||||
|
||||
|
||||
double candleClose = iClose(_Symbol,_timeFrame,_index);
|
||||
double candleOpen = iOpen(_Symbol,_timeFrame,_index);
|
||||
|
||||
|
||||
if(candleClose < candleOpen) // the candle closed bullish
|
||||
{
|
||||
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void deleteZoneWithGUI(string _id)
|
||||
{
|
||||
|
||||
|
||||
zoneContainer.deleteZone(_id);
|
||||
|
||||
if(!ObjectDelete(_Symbol,_id))
|
||||
{
|
||||
Print("Failed to delete object error: " + GetLastError());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void deleteZoneGuiOnly(string _id)
|
||||
{
|
||||
|
||||
|
||||
if(!ObjectDelete(_Symbol,_id))
|
||||
{
|
||||
Print("Failed to delete object error: " + GetLastError());
|
||||
}
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
bool candleClosedBelowRetestZone(ENUM_TIMEFRAMES tf){
|
||||
|
||||
|
||||
double previousCandleClose = iClose(_Symbol,tf,1);
|
||||
|
||||
if(previousCandleClose < temporaryRestestSupportZone.getLowerEdge() ){
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void closePartialsOfAllTrades(double partial){
|
||||
for(int i = PositionsTotal()-1 ; i>=0 ; i--){
|
||||
ulong posTicket = PositionGetTicket(i);
|
||||
if(PositionSelectByTicket(posTicket)){
|
||||
double positionVolum = PositionGetDouble(POSITION_VOLUME);
|
||||
double partialToClose = positionVolum * partial ;
|
||||
tradeTiger.PositionClosePartial(posTicket,NormalizeDouble(partialToClose,2));
|
||||
|
||||
}
|
||||
else{
|
||||
Print("Failed to select position, Error: " + GetLastError());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void secureTenPips(double partial){
|
||||
|
||||
for(int i = PositionsTotal()-1 ; i>=0 ; i--){
|
||||
ulong posTicket = PositionGetTicket(i);
|
||||
if(PositionSelectByTicket(posTicket)){
|
||||
double positionVolume = PositionGetDouble(POSITION_VOLUME);
|
||||
|
||||
if((SymbolInfoDouble(_Symbol, SYMBOL_BID) - PositionGetDouble(POSITION_PRICE_OPEN)) > 1){
|
||||
double partialToClose = positionVolume * partial ;
|
||||
tradeTiger.PositionClosePartial(posTicket,NormalizeDouble(partialToClose,2));
|
||||
securedTenPips = true ;
|
||||
Print("secured 10 pips");
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else{
|
||||
Print("Failed to select position, Error: " + GetLastError());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Binary file not shown.
+1023
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1442
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -0,0 +1,694 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| TigerObserver.mq5 |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include "NewCandleDetector.mqh"
|
||||
#include "GraphicalObjectsManager.mqh"
|
||||
#include "Zone.mqh"
|
||||
#include "ZoneContainer.mqh"
|
||||
|
||||
#include "MarketObserverTiger.mqh"
|
||||
|
||||
|
||||
input group "Range Related Variables"
|
||||
input double rangeDistanceBetweenZones ;
|
||||
input double cleanRangeUponEntry ;
|
||||
input double potentialRR;
|
||||
|
||||
input group "Zone Size Settings"
|
||||
input double resistanceExtendAboveCandle;
|
||||
input double resistanceLowerEdgeExtend ;
|
||||
input double supportExtendBelowCandle ;
|
||||
input double supportHigherEdgeExtend;
|
||||
|
||||
input group "Zone TimeFrames"
|
||||
input bool APPLY_M30_STRUCTURE ;
|
||||
input bool APPLY_H1_STRUCTURE;
|
||||
|
||||
|
||||
// GUI CLASSES INITIALIZATION
|
||||
GraphicalObjectsManager* objectsManager = new GraphicalObjectsManager();
|
||||
|
||||
// CONTAINERS INITIALIZATION
|
||||
|
||||
|
||||
ZoneContainer* zoneContainer_W1 = new ZoneContainer() ;
|
||||
ZoneContainer* zoneContainer_D1 = new ZoneContainer() ;
|
||||
ZoneContainer* zoneContainer_H4 = new ZoneContainer() ;
|
||||
ZoneContainer* zoneContainer_H1 = new ZoneContainer() ;
|
||||
ZoneContainer* zoneContainer_M30 = new ZoneContainer() ;
|
||||
|
||||
|
||||
ZoneContainer* zoneContainerSupport_W1 = new ZoneContainer() ;
|
||||
ZoneContainer* zoneContainerSupport_D1 = new ZoneContainer() ;
|
||||
ZoneContainer* zoneContainerSupport_H4 = new ZoneContainer() ;
|
||||
ZoneContainer* zoneContainerSupport_H1 = new ZoneContainer() ;
|
||||
ZoneContainer* zoneContainerSupport_M30 = new ZoneContainer() ;
|
||||
|
||||
|
||||
|
||||
// ALGORITHM CLASSES INITIALIZATION
|
||||
MarketObserverTiger* marketObserverTiger = new MarketObserverTiger();
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
NewCandleDetector newCandleDetectorWeekly("PERIOD_W1");
|
||||
NewCandleDetector newCandleDetectorDaily("PERIOD_D1");
|
||||
NewCandleDetector newCandleDetector4H("PERIOD_H4");
|
||||
NewCandleDetector newCandleDetector1H("PERIOD_H1");
|
||||
NewCandleDetector newCandleDetector30M("PERIOD_M30");
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
Zone* temporaryRestestSupportZone = new Zone();
|
||||
|
||||
int OnInit()
|
||||
{
|
||||
//--- create timer
|
||||
EventSetTimer(60);
|
||||
|
||||
// ONLY FOR VISULAZITAION ON STRATEGY TESTER
|
||||
iClose(_Symbol,PERIOD_W1,1);
|
||||
iClose(_Symbol,PERIOD_D1,1);
|
||||
iClose(_Symbol,PERIOD_H4,5);
|
||||
iClose(_Symbol,PERIOD_H1,5);
|
||||
iClose(_Symbol,PERIOD_M30,5);
|
||||
iClose(_Symbol,PERIOD_M15,5);
|
||||
|
||||
objectsManager.addTextTiger();
|
||||
//objectsManager.addMarketDescriptionTextTiger();
|
||||
|
||||
//---
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- destroy timer
|
||||
EventKillTimer();
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//---
|
||||
|
||||
/*if(newCandleDetector30M.isNewCandle())
|
||||
{
|
||||
|
||||
detectAndDrawResistanceOnTimeFrame(PERIOD_M30,"PERIOD_M30",clrPink,clrBlue,zoneContainer_M30);
|
||||
updateBreakAboveStructureAndDelete(zoneContainer_M30,PERIOD_M30,"PERIOD_M30");
|
||||
|
||||
detectAndDrawSupportOnTimeFrame(PERIOD_M30,"PERIOD_M30",clrYellow,clrGreen,zoneContainerSupport_M30);
|
||||
updateBreakBelowStructureAndDelete(zoneContainerSupport_M30,PERIOD_M30,"PERIOD_M30");
|
||||
|
||||
|
||||
datetime currTime = TimeCurrent();
|
||||
ObjectSetString(0,"clockTextTiger",OBJPROP_TEXT,TimeToString(currTime,TIME_MINUTES));
|
||||
|
||||
} */
|
||||
|
||||
|
||||
/*if(newCandleDetector1H.isNewCandle()){
|
||||
|
||||
|
||||
MqlDateTime mqldt ;
|
||||
datetime currTime = TimeCurrent(mqldt);
|
||||
if(mqldt.hour == 13){
|
||||
|
||||
objectsManager.drawVerticalLine(clrAzure,TimeCurrent());
|
||||
|
||||
}
|
||||
detectAndDrawResistanceOnTimeFrame(PERIOD_H1,"PERIOD_H1",clrGray,clrRed,zoneContainer_H1);
|
||||
updateBreakAboveStructureAndDelete(zoneContainer_H1,PERIOD_H1,"PERIOD_H1");
|
||||
|
||||
detectAndDrawSupportOnTimeFrame(PERIOD_H1,"PERIOD_H1",clrWhite,clrRed,zoneContainerSupport_H1);
|
||||
updateBreakBelowStructureAndDelete(zoneContainerSupport_H1,PERIOD_H1,"PERIOD_H1");
|
||||
|
||||
|
||||
//zoneContainer_H1.printZonesSortedArray();
|
||||
//zoneContainerSupport_H1.printZonesSortedArray();
|
||||
|
||||
} */
|
||||
|
||||
|
||||
|
||||
if(newCandleDetector4H.isNewCandle()){
|
||||
|
||||
detectAndDrawResistanceOnTimeFrame(PERIOD_H4,"PERIOD_H4",clrPurple,clrGreen,zoneContainer_H4);
|
||||
updateBreakAboveStructureAndDelete(zoneContainer_H4,PERIOD_H4,"PERIOD_H4");
|
||||
|
||||
detectAndDrawResistanceOnTimeFrame(PERIOD_H4,"PERIOD_H4",clrPink,clrBlue,zoneContainer_H4);
|
||||
updateBreakAboveStructureAndDelete(zoneContainer_H4,PERIOD_H4,"PERIOD_H4");
|
||||
|
||||
detectAndDrawSupportOnTimeFrame(PERIOD_H4,"PERIOD_H4",clrYellow,clrGreen,zoneContainerSupport_H4);
|
||||
updateBreakBelowStructureAndDelete(zoneContainerSupport_H4,PERIOD_H4,"PERIOD_H4");
|
||||
|
||||
|
||||
datetime currTime = TimeCurrent();
|
||||
ObjectSetString(0,"clockTextTiger",OBJPROP_TEXT,TimeToString(currTime,TIME_MINUTES));
|
||||
}
|
||||
|
||||
if(newCandleDetectorDaily.isNewCandle()){
|
||||
|
||||
//detectAndDrawResistanceOnTimeFrame(PERIOD_D1,"PERIOD_D1",clrYellow,clrYellow,zoneContainer_D1);
|
||||
//updateBreakAboveStructureAndDelete(zoneContainer_D1,PERIOD_D1,"PERIOD_D1");
|
||||
objectsManager.drawVerticalLine(clrAqua, TimeCurrent());
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(newCandleDetectorWeekly.isNewCandle()){
|
||||
|
||||
objectsManager.drawVerticalLine(clrRed, TimeCurrent());;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Timer function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTimer()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Trade function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTrade()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TradeTransaction function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTradeTransaction(const MqlTradeTransaction& trans,
|
||||
const MqlTradeRequest& request,
|
||||
const MqlTradeResult& result)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Tester function |
|
||||
//+------------------------------------------------------------------+
|
||||
double OnTester()
|
||||
{
|
||||
//---
|
||||
double ret=0.0;
|
||||
//---
|
||||
|
||||
//---
|
||||
return(ret);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterInit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterInit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterPass function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterPass()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterDeinit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterDeinit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnChartEvent(const int id,
|
||||
const long &lparam,
|
||||
const double &dparam,
|
||||
const string &sparam)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| BookEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnBookEvent(const string &symbol)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool detectAndDrawResistanceOnTimeFrame(ENUM_TIMEFRAMES timeFrame, string timeFrameStr, long BOS_zone_color, long usual_zone_color,ZoneContainer& zoneContainer )
|
||||
{
|
||||
|
||||
|
||||
if(candleClosedBullish(timeFrame,2) && candleClosedBearish(timeFrame,1)) // if resistance formed
|
||||
{
|
||||
|
||||
// create a rectangle with a unique name
|
||||
int currentIdCounter = zoneContainer.getZonesIdCounter();
|
||||
|
||||
|
||||
datetime _leftEdge = iTime(_Symbol,timeFrame,2);
|
||||
datetime _rightEdge = D'2023.11.01 00:00:00';
|
||||
double resistancePrice = iOpen(_Symbol,timeFrame,1);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if((zoneContainer.getNumberOfActiveZones() != 0) && (zoneContainer.getZoneByIndex(0).getLowerEdge() - resistancePrice >= rangeDistanceBetweenZones)) // check if it has a clean range above
|
||||
{
|
||||
|
||||
Zone* newZone = new Zone() ;
|
||||
newZone.setHigherEdgePrice(resistancePrice + resistanceExtendAboveCandle);
|
||||
newZone.setLowerEdgePrice(resistancePrice - resistanceLowerEdgeExtend);
|
||||
newZone.setLeftEdge(_leftEdge);
|
||||
newZone.setRightEdge(_rightEdge);
|
||||
newZone.setId(IntegerToString(currentIdCounter));
|
||||
newZone.setTimeFrame(timeFrameStr);
|
||||
newZone.setType("TYPE_RESISTANCE_BREAKOUT");
|
||||
|
||||
|
||||
|
||||
|
||||
zoneContainer.addResistanceZoneTiger(newZone);
|
||||
zoneContainer.incrementZonesIdCounter();
|
||||
|
||||
Print("current id counter of, zoneContainer is: " + currentIdCounter );
|
||||
objectsManager.drawRectangleInStrategyTester(currentIdCounter,_leftEdge,_rightEdge,resistancePrice + resistanceExtendAboveCandle,resistancePrice - resistanceLowerEdgeExtend,BOS_zone_color);
|
||||
//Print("Number of active zones is: " + zoneContainer.getNumberOfActiveZones());
|
||||
//zoneContainer.printZonesSortedArray();
|
||||
}
|
||||
|
||||
else
|
||||
if((zoneContainer.getNumberOfActiveZones() != 0) && (zoneContainer.getZoneByIndex(0).getLowerEdge() - resistancePrice < rangeDistanceBetweenZones)) // if it doesnt have a clean range, just add it as a blue zone
|
||||
{
|
||||
double currentHighEdge = resistancePrice + resistanceExtendAboveCandle ; // this is a high edge of a resistance, but its not considered as a zone, because it doesnt have clean range above
|
||||
double currentLowEdge = resistancePrice - resistanceLowerEdgeExtend; // this is a low edge of a resistance, but its not considered as a zone, because it doesnt have clean range above
|
||||
|
||||
Zone* newZone = new Zone() ;
|
||||
newZone.setHigherEdgePrice(resistancePrice + resistanceExtendAboveCandle);
|
||||
newZone.setLowerEdgePrice(resistancePrice - resistanceLowerEdgeExtend);
|
||||
newZone.setLeftEdge(_leftEdge);
|
||||
newZone.setRightEdge(_rightEdge);
|
||||
newZone.setId(IntegerToString(currentIdCounter));
|
||||
newZone.setTimeFrame(timeFrameStr);
|
||||
newZone.setType("TYPE_RESISTANCE_NORMAL");
|
||||
|
||||
zoneContainer.addResistanceZoneTiger(newZone);
|
||||
zoneContainer.incrementZonesIdCounter();
|
||||
|
||||
//objectsManager.drawRectangleInStrategyTester(currentIdCounter,_leftEdge,_rightEdge,resistancePrice + resistanceExtendAboveCandle,resistancePrice,usual_zone_color);
|
||||
|
||||
/*if(zoneContainer.getZoneByIndex(1).getType() == "TYPE_RESISTANCE_NORMAL"){
|
||||
string idOfZoneToHide = zoneContainer.getZoneByIndex(1).getId();
|
||||
deleteZoneGuiOnly(idOfZoneToHide,zoneContainer);
|
||||
} */
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
if(zoneContainer.getNumberOfActiveZones() == 0) // this means this is the first zone to add to the data strucutre
|
||||
{
|
||||
|
||||
//Print("Entered here 2");
|
||||
Zone* newZone = new Zone() ;
|
||||
newZone.setHigherEdgePrice(resistancePrice + resistanceExtendAboveCandle);
|
||||
newZone.setLowerEdgePrice(resistancePrice - resistanceLowerEdgeExtend);
|
||||
newZone.setLeftEdge(_leftEdge);
|
||||
newZone.setRightEdge(_rightEdge);
|
||||
newZone.setId(IntegerToString(currentIdCounter));
|
||||
newZone.setTimeFrame(timeFrameStr);
|
||||
newZone.setType("TYPE_RESISTANCE_BREAKOUT");
|
||||
|
||||
|
||||
|
||||
zoneContainer.addResistanceZoneTiger(newZone);
|
||||
zoneContainer.incrementZonesIdCounter();
|
||||
|
||||
|
||||
objectsManager.drawRectangleInStrategyTester(currentIdCounter,_leftEdge,_rightEdge,resistancePrice + resistanceExtendAboveCandle,resistancePrice - resistanceLowerEdgeExtend,BOS_zone_color);
|
||||
//zoneContainer.printZonesSortedArray();
|
||||
}
|
||||
|
||||
return true ;
|
||||
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool detectAndDrawSupportOnTimeFrame(ENUM_TIMEFRAMES timeFrame, string timeFrameStr, long BOS_zone_color, long usual_zone_color,ZoneContainer& zoneContainer )
|
||||
{
|
||||
|
||||
|
||||
if(candleClosedBearish(timeFrame,2) && candleClosedBullish(timeFrame,1)) // if support formed
|
||||
{
|
||||
|
||||
// create a rectangle with a unique name
|
||||
int currentIdCounter = zoneContainer.getSupportZonesIdCounter();
|
||||
|
||||
|
||||
datetime _leftEdge = iTime(_Symbol,timeFrame,2);
|
||||
datetime _rightEdge = D'2023.11.01 00:00:00';
|
||||
double supportPrice = iOpen(_Symbol,timeFrame,1);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if((zoneContainer.getNumberOfActiveZones() != 0) && (supportPrice - zoneContainer.getZoneByIndex(zoneContainer.getNumberOfActiveZones()-1).getHigherEdge() >= rangeDistanceBetweenZones)) // check if it has a clean range down
|
||||
{
|
||||
|
||||
Zone* newZone = new Zone() ;
|
||||
newZone.setLowerEdgePrice(supportPrice - supportExtendBelowCandle);
|
||||
newZone.setHigherEdgePrice(supportPrice + supportHigherEdgeExtend);
|
||||
newZone.setLeftEdge(_leftEdge);
|
||||
newZone.setRightEdge(_rightEdge);
|
||||
newZone.setId(IntegerToString(currentIdCounter));
|
||||
newZone.setTimeFrame(timeFrameStr);
|
||||
newZone.setType("TYPE_SUPPORT_BREAKOUT");
|
||||
|
||||
|
||||
|
||||
|
||||
zoneContainer.addSupportZoneTiger(newZone);
|
||||
zoneContainer.incrementZonesIdCounterSupport();
|
||||
|
||||
Print("current id counter of, zoneContainer_support is: " + currentIdCounter );
|
||||
objectsManager.drawRectangleInStrategyTester(currentIdCounter,_leftEdge,_rightEdge,supportPrice + supportHigherEdgeExtend,supportPrice- supportExtendBelowCandle,BOS_zone_color);
|
||||
//Print("Number of active zones is: " + zoneContainer.getNumberOfActiveZones());
|
||||
//zoneContainer.printZonesSortedArray();
|
||||
}
|
||||
|
||||
else
|
||||
if((zoneContainer.getNumberOfActiveZones() != 0) && (supportPrice - zoneContainer.getZoneByIndex(zoneContainer.getNumberOfActiveZones()-1).getHigherEdge() < rangeDistanceBetweenZones)) // if it doesnt have a clean range, just add it as a blue zone
|
||||
{
|
||||
double currentHighEdge = supportPrice + supportHigherEdgeExtend ; // this is a high edge of a resistance, but its not considered as a zone, because it doesnt have clean range above
|
||||
double currentLowEdge = supportPrice - supportExtendBelowCandle; // this is a low edge of a resistance, but its not considered as a zone, because it doesnt have clean range above
|
||||
|
||||
Zone* newZone = new Zone() ;
|
||||
newZone.setHigherEdgePrice(supportPrice + supportHigherEdgeExtend);
|
||||
newZone.setLowerEdgePrice(supportPrice - supportExtendBelowCandle);
|
||||
newZone.setLeftEdge(_leftEdge);
|
||||
newZone.setRightEdge(_rightEdge);
|
||||
newZone.setId(IntegerToString(currentIdCounter));
|
||||
newZone.setTimeFrame(timeFrameStr);
|
||||
newZone.setType("TYPE_SUPPORT_NORMAL");
|
||||
|
||||
zoneContainer.addSupportZoneTiger(newZone);
|
||||
zoneContainer.incrementZonesIdCounterSupport();
|
||||
//objectsManager.drawRectangleInStrategyTester(currentIdCounter,_leftEdge,_rightEdge,supportPrice,supportPrice - supportExtendBelowCandle,usual_zone_color);
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
if(zoneContainer.getNumberOfActiveZones() == 0) // this means this is the first zone to add to the data strucutre
|
||||
{
|
||||
|
||||
//Print("Entered here 2");
|
||||
Zone* newZone = new Zone() ;
|
||||
newZone.setHigherEdgePrice(supportPrice + supportHigherEdgeExtend);
|
||||
newZone.setLowerEdgePrice(supportPrice - supportExtendBelowCandle);
|
||||
newZone.setLeftEdge(_leftEdge);
|
||||
newZone.setRightEdge(_rightEdge);
|
||||
newZone.setId(IntegerToString(currentIdCounter));
|
||||
newZone.setTimeFrame(timeFrameStr);
|
||||
newZone.setType("TYPE_SUPPORT_BREAKOUT");
|
||||
|
||||
|
||||
zoneContainer.addSupportZoneTiger(newZone);
|
||||
zoneContainer.incrementZonesIdCounterSupport();
|
||||
|
||||
|
||||
objectsManager.drawRectangleInStrategyTester(currentIdCounter,_leftEdge,_rightEdge,supportPrice + supportHigherEdgeExtend,supportPrice - supportExtendBelowCandle,BOS_zone_color);
|
||||
//zoneContainer.printZonesSortedArray();
|
||||
}
|
||||
|
||||
|
||||
return true ;
|
||||
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool candleClosedBullish(ENUM_TIMEFRAMES _timeFrame, int _index)
|
||||
{
|
||||
double candleClose = iClose(_Symbol,_timeFrame,_index);
|
||||
double candleOpen = iOpen(_Symbol,_timeFrame,_index);
|
||||
|
||||
|
||||
if(candleClose >candleOpen) // the candle closed bullish
|
||||
{
|
||||
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool candleClosedBearish(ENUM_TIMEFRAMES _timeFrame,int _index)
|
||||
{
|
||||
|
||||
|
||||
double candleClose = iClose(_Symbol,_timeFrame,_index);
|
||||
double candleOpen = iOpen(_Symbol,_timeFrame,_index);
|
||||
|
||||
|
||||
if(candleClose < candleOpen) // the candle closed bullish
|
||||
{
|
||||
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
void deleteZoneWithGUI(string _id, ZoneContainer& zoneContainer)
|
||||
{
|
||||
|
||||
|
||||
zoneContainer.deleteZone(_id);
|
||||
|
||||
if(!ObjectDelete(_Symbol,_id))
|
||||
{
|
||||
Print("Failed to delete object error: " + GetLastError());
|
||||
}
|
||||
|
||||
|
||||
Print("Deleted the zone with gui!");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void deleteZoneGuiOnly(string _id,ZoneContainer& zoneContainer)
|
||||
{
|
||||
|
||||
|
||||
if(!ObjectDelete(_Symbol,_id))
|
||||
{
|
||||
Print("Failed to delete object error: " + GetLastError());
|
||||
}
|
||||
|
||||
Print("Deleted the zone gui!");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void updateBreakAboveStructureAndDelete(ZoneContainer& zoneContainer, ENUM_TIMEFRAMES timeFrame, string timeFrameStr){
|
||||
bool finishedDeleting = false ;
|
||||
|
||||
if(zoneContainer.getNumberOfActiveZones() != 0) // if there are zones found
|
||||
{
|
||||
if(marketObserverTiger.candleClosedAboveResistanceByIndex(0,timeFrame,zoneContainer)) // check if candle closed above the zone
|
||||
{
|
||||
|
||||
|
||||
|
||||
datetime _leftEdgeRestestZone = iTime(_Symbol,timeFrame,4);
|
||||
datetime _rightEdgeRetestZone = D'2023.11.01 00:00:00';
|
||||
|
||||
|
||||
while(!finishedDeleting && zoneContainer.getNumberOfActiveZones() != 0 ) // this while is used in the case of a candle closing above more than 1 zone at once
|
||||
{
|
||||
/* temporaryRestestSupportZone.setHigherEdgePrice(zoneContainer.getZoneByIndex(0).getHigherEdge());
|
||||
temporaryRestestSupportZone.setLowerEdgePrice(zoneContainer.getZoneByIndex(0).getLowerEdge());
|
||||
temporaryRestestSupportZone.setLeftEdge(_leftEdgeRestestZone);
|
||||
temporaryRestestSupportZone.setRightEdge(_rightEdgeRetestZone);
|
||||
temporaryRestestSupportZone.setId("999"); // the + "t" stands for temporary and it is made to keep the zones id's unique
|
||||
temporaryRestestSupportZone.setTimeFrame("PERIOD_M30");
|
||||
temporaryRestestSupportZone.setType("TYPE_SUPPORT");
|
||||
deleteZoneWithGUI((zoneContainer.getZoneByIndex(0).getId())); // delete the zone with the GUI */
|
||||
|
||||
if(zoneContainer.getNumberOfActiveZones() != 0 && marketObserverTiger.candleClosedAboveResistanceByIndex(0,timeFrame,zoneContainer))
|
||||
{
|
||||
zoneContainer.getZoneByIndex(0).getHigherEdge();
|
||||
temporaryRestestSupportZone.setHigherEdgePrice(zoneContainer.getZoneByIndex(0).getHigherEdge());
|
||||
temporaryRestestSupportZone.setLowerEdgePrice(zoneContainer.getZoneByIndex(0).getLowerEdge());
|
||||
temporaryRestestSupportZone.setLeftEdge(_leftEdgeRestestZone);
|
||||
temporaryRestestSupportZone.setRightEdge(_rightEdgeRetestZone);
|
||||
temporaryRestestSupportZone.setId("999"); // the + "t" stands for temporary and it is made to keep the zones id's unique
|
||||
temporaryRestestSupportZone.setTimeFrame(timeFrameStr);
|
||||
temporaryRestestSupportZone.setType("TYPE_SUPPORT");
|
||||
deleteZoneWithGUI((zoneContainer.getZoneByIndex(0).getId()),zoneContainer); // delete the zone with the GUI
|
||||
}
|
||||
else
|
||||
{
|
||||
finishedDeleting = true ;
|
||||
ObjectSetString(0,"marketDescriptionText",OBJPROP_TEXT,"");
|
||||
ObjectSetString(0,"marketDescriptionText",OBJPROP_TEXT,"");
|
||||
ObjectSetString(0,"marketDescriptionText",OBJPROP_TEXT,"Candle Closed Above the zone");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*if(zoneContainer.getNumberOfActiveZones() != 0 && zoneContainer.getZoneByIndex(0).getType() == "TYPE_RESISTANCE_NORMAL"){
|
||||
|
||||
Zone* tempZone = zoneContainer.getZoneByIndex(0);
|
||||
string zoneIdStr = tempZone.getId();
|
||||
int zoneIdInteger = StringToInteger(zoneIdStr);
|
||||
|
||||
objectsManager.drawRectangleInStrategyTester(zoneIdInteger,tempZone.getLeftEdge(),tempZone.getRightEdge(),tempZone.getHigherEdge(),tempZone.getLowerEdge(),clrRed);
|
||||
Print("Retrieved the zone succesfully!");
|
||||
|
||||
|
||||
} */
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void updateBreakBelowStructureAndDelete(ZoneContainer& zoneContainer, ENUM_TIMEFRAMES timeFrame, string timeFrameStr){
|
||||
bool finishedDeleting = false ;
|
||||
|
||||
if(zoneContainer.getNumberOfActiveZones() != 0) // if there are zones found
|
||||
{
|
||||
|
||||
if(marketObserverTiger.candleClosedBelowSupportByIndex(zoneContainer.getNumberOfActiveZones() -1 ,timeFrame,zoneContainer)) // check if candle closed below the zone
|
||||
{
|
||||
|
||||
|
||||
datetime _leftEdgeRestestZone = iTime(_Symbol,timeFrame,4);
|
||||
datetime _rightEdgeRetestZone = D'2023.11.01 00:00:00';
|
||||
|
||||
|
||||
while(!finishedDeleting && zoneContainer.getNumberOfActiveZones() != 0 ) // this while is used in the case of a candle closing above more than 1 zone at once
|
||||
{
|
||||
/* temporaryRestestSupportZone.setHigherEdgePrice(zoneContainer.getZoneByIndex(0).getHigherEdge());
|
||||
temporaryRestestSupportZone.setLowerEdgePrice(zoneContainer.getZoneByIndex(0).getLowerEdge());
|
||||
temporaryRestestSupportZone.setLeftEdge(_leftEdgeRestestZone);
|
||||
temporaryRestestSupportZone.setRightEdge(_rightEdgeRetestZone);
|
||||
temporaryRestestSupportZone.setId("999"); // the + "t" stands for temporary and it is made to keep the zones id's unique
|
||||
temporaryRestestSupportZone.setTimeFrame("PERIOD_M30");
|
||||
temporaryRestestSupportZone.setType("TYPE_SUPPORT");
|
||||
deleteZoneWithGUI((zoneContainer.getZoneByIndex(0).getId())); // delete the zone with the GUI */
|
||||
|
||||
if(zoneContainer.getNumberOfActiveZones() != 0 && marketObserverTiger.candleClosedBelowSupportByIndex(zoneContainer.getNumberOfActiveZones()-1,timeFrame,zoneContainer))
|
||||
{
|
||||
zoneContainer.getZoneByIndex(zoneContainer.getNumberOfActiveZones()-1).getHigherEdge();
|
||||
temporaryRestestSupportZone.setHigherEdgePrice(zoneContainer.getZoneByIndex(zoneContainer.getNumberOfActiveZones()-1).getHigherEdge());
|
||||
temporaryRestestSupportZone.setLowerEdgePrice(zoneContainer.getZoneByIndex(zoneContainer.getNumberOfActiveZones()-1).getLowerEdge());
|
||||
temporaryRestestSupportZone.setLeftEdge(_leftEdgeRestestZone);
|
||||
temporaryRestestSupportZone.setRightEdge(_rightEdgeRetestZone);
|
||||
temporaryRestestSupportZone.setId("9999"); // the + "t" stands for temporary and it is made to keep the zones id's unique
|
||||
temporaryRestestSupportZone.setTimeFrame(timeFrameStr);
|
||||
temporaryRestestSupportZone.setType("TYPE_RESISTANCE");
|
||||
|
||||
deleteZoneWithGUI((zoneContainer.getZoneByIndex(zoneContainer.getNumberOfActiveZones()-1).getId()),zoneContainer); // delete the zone with the GUI
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//Print("Lower edge is: " + zoneContainer.getZoneByIndex(zoneContainer.getNumberOfActiveZones()-1).getLowerEdge());
|
||||
finishedDeleting = true ;
|
||||
ObjectSetString(0,"marketDescriptionText",OBJPROP_TEXT,"");
|
||||
ObjectSetString(0,"marketDescriptionText",OBJPROP_TEXT,"");
|
||||
ObjectSetString(0,"marketDescriptionText",OBJPROP_TEXT,"Candle Closed Below the zone");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*if(zoneContainer.getNumberOfActiveZones() != 0 && zoneContainer.getZoneByIndex(0).getType() == "TYPE_RESISTANCE_NORMAL"){
|
||||
|
||||
Zone* tempZone = zoneContainer.getZoneByIndex(0);
|
||||
string zoneIdStr = tempZone.getId();
|
||||
int zoneIdInteger = StringToInteger(zoneIdStr);
|
||||
|
||||
objectsManager.drawRectangleInStrategyTester(zoneIdInteger,tempZone.getLeftEdge(),tempZone.getRightEdge(),tempZone.getHigherEdge(),tempZone.getLowerEdge(),clrRed);
|
||||
Print("Retrieved the zone succesfully!");
|
||||
|
||||
|
||||
} */
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -0,0 +1,443 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| TigerObserver.mq5 |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#include "Algo_Skeleton_Functions.mqh"
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
//--- create timer
|
||||
EventSetTimer(60);
|
||||
|
||||
// ONLY FOR VISULAZITAION ON STRATEGY TESTER
|
||||
iClose(_Symbol,PERIOD_W1,1);
|
||||
iClose(_Symbol,PERIOD_D1,1);
|
||||
iClose(_Symbol,PERIOD_H4,5);
|
||||
iClose(_Symbol,PERIOD_H1,5);
|
||||
iClose(_Symbol,PERIOD_M30,5);
|
||||
iClose(_Symbol,PERIOD_M15,5);
|
||||
|
||||
objectsManager.addTextTiger();
|
||||
|
||||
for(int i=0; i<NUM_MAX_ALLOWED_TRADES ; i++)
|
||||
{
|
||||
BuyActiveTradesArray[i] = NULL ;
|
||||
SellActiveTradesArray[i] = NULL ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//objectsManager.addMarketDescriptionTextTiger();
|
||||
|
||||
//---
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- destroy timer
|
||||
Print("Buys Count: " + buysCount);
|
||||
Print("Sells Count: " + sellsCount);
|
||||
EventKillTimer();
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
|
||||
cleanBuyTradesArr();
|
||||
cleanSellTradesArr();
|
||||
secureProfitIfNeeded();
|
||||
|
||||
// BUYS
|
||||
if(waitForBottomWickToForm == true && wickLengthCounter == wickLengthInMinutes) // waited wickLengthInMinutes time, and now its the time to check if the wick is valid
|
||||
{
|
||||
|
||||
bottomWickValidationState = handleBottomWickValidation();
|
||||
updateBottomWickState(bottomWickValidationState);
|
||||
|
||||
}
|
||||
|
||||
if(bottomWickFormed){
|
||||
datetime currTime = TimeCurrent();
|
||||
if(SymbolInfoDouble(_Symbol,SYMBOL_ASK) >= buyStopPrice && !wickTradeTaken){
|
||||
double stopLossPrice = iLow(_Symbol,PERIOD_CURRENT,0) - stopLossUnderWickBy;
|
||||
|
||||
double stopLossBased_H1 = iLow(_Symbol,PERIOD_H1,1);
|
||||
double stopLossBased_M30 = iLow(_Symbol,PERIOD_M30,1);
|
||||
double stopLossBased_M15 = iLow(_Symbol,PERIOD_M15,1);
|
||||
|
||||
stopLossBased_H1 = stopLossBased_H1 - stopLossUnderWickBy ;
|
||||
stopLossBased_M30 = stopLossBased_M30 - stopLossUnderWickBy ;
|
||||
stopLossBased_M15 = stopLossBased_M15 - stopLossUnderWickBy ;
|
||||
|
||||
|
||||
if((SymbolInfoDouble(_Symbol,SYMBOL_ASK) - stopLossPrice) < minimumStopLossInPips){
|
||||
stopLossPrice = stopLossBased_M30 ;
|
||||
if(stopLossIsValidBuys(stopLossBased_H1,maxPipsRiskAmount)){
|
||||
stopLossPrice = stopLossBased_H1 ;
|
||||
}
|
||||
else if(stopLossIsValidBuys(stopLossBased_M30,maxPipsRiskAmount)){
|
||||
stopLossPrice = stopLossBased_M30 ;
|
||||
}
|
||||
|
||||
else if(stopLossIsValidBuys(stopLossBased_M15,maxPipsRiskAmount)){
|
||||
stopLossPrice = stopLossBased_M15 ;
|
||||
}
|
||||
}
|
||||
else if(!stopLossIsValidBuys(stopLossPrice,maxPipsRiskAmount)){
|
||||
stopLossPrice = -1 ;
|
||||
}
|
||||
double lotsToBuy = lsCalc.calculateLotSize(riskDollars,stopLossPrice);
|
||||
int indexToNewTrade ;
|
||||
if(((indexToNewTrade = findAvailableSpotInBuyManagerArr()) != -1) && stopLossPrice != -1)
|
||||
{
|
||||
|
||||
|
||||
activeTradeId = buyEntryManager.takeBuyTradeTiger(lotsToBuy,stopLossPrice) ;
|
||||
|
||||
BuyTradeManagerTiger* tempTigerManager= new BuyTradeManagerTiger(activeTradeId); // create an object of type sellTradeManagerTiger
|
||||
BuyActiveTradesArray[indexToNewTrade] = tempTigerManager ;// put the new object in the array
|
||||
buysCount++;
|
||||
wickTradeTaken = true ;
|
||||
Comment("Took a bUY. stop loss: above current wick, " + "Active trade id: " + activeTradeId);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Comment("i cant take a trade because the arrray is full");
|
||||
}
|
||||
Comment(TimeToString(currTime,TIME_MINUTES) + ": price has reached the candle high, im taking a buy");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// SELLS
|
||||
|
||||
if(waitForTopWickToForm == true && wickLengthCounter == wickLengthInMinutes){ // waited wickLengthInMinutes time, and now its the time to check if the wick is valid
|
||||
topWickValidationState = handleTopWickValidation();
|
||||
updateTopWickState(topWickValidationState);
|
||||
}
|
||||
|
||||
if(topWickFormed){
|
||||
datetime currTime = TimeCurrent();
|
||||
if((SymbolInfoDouble(_Symbol,SYMBOL_BID) <= sellStopPrice) && !wickTradeTaken){
|
||||
double stopLossPrice = iHigh(_Symbol,PERIOD_CURRENT,0) + stopLossAboveWickBy;
|
||||
|
||||
|
||||
double stopLossBased_H1 = iHigh(_Symbol,PERIOD_H1,1);
|
||||
double stopLossBased_M30 = iHigh(_Symbol,PERIOD_M30,1);
|
||||
double stopLossBased_M15 = iHigh(_Symbol,PERIOD_M15,1);
|
||||
|
||||
stopLossBased_H1 = stopLossBased_H1 + stopLossAboveWickBy ;
|
||||
stopLossBased_M30 = stopLossBased_M30 + stopLossAboveWickBy ;
|
||||
stopLossBased_M15 = stopLossBased_M15 + stopLossAboveWickBy ;
|
||||
|
||||
if((stopLossPrice - SymbolInfoDouble(_Symbol,SYMBOL_BID)) < minimumStopLossInPips){
|
||||
stopLossPrice = stopLossBased_M30 ;
|
||||
if(stopLossIsValidSells(stopLossBased_H1,maxPipsRiskAmount)){
|
||||
stopLossPrice = stopLossBased_H1 ;
|
||||
}
|
||||
else if(stopLossIsValidSells(stopLossBased_M30,maxPipsRiskAmount)){
|
||||
stopLossPrice = stopLossBased_M30 ;
|
||||
}
|
||||
|
||||
else if(stopLossIsValidSells(stopLossBased_M15,maxPipsRiskAmount)){
|
||||
stopLossPrice = stopLossBased_M15 ;
|
||||
}
|
||||
}
|
||||
else if(!stopLossIsValidSells(stopLossPrice,maxPipsRiskAmount)){
|
||||
stopLossPrice = -1 ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double lotsToSell = lsCalc.calculateLotSize(riskDollars,stopLossPrice);
|
||||
|
||||
int indexToNewTrade ;
|
||||
|
||||
if(((indexToNewTrade = findAvailableSpotInSellManagerArr()) != -1) && stopLossPrice != -1)
|
||||
{
|
||||
|
||||
|
||||
activeTradeId = sellEntryManager.takeSellTradeTiger(lotsToSell,stopLossPrice) ;
|
||||
|
||||
SellTradeManagerTiger* tempTigerManager= new SellTradeManagerTiger(activeTradeId); // create an object of type sellTradeManagerTiger
|
||||
SellActiveTradesArray[indexToNewTrade] = tempTigerManager ;// put the new object in the array
|
||||
sellsCount++;
|
||||
wickTradeTaken = true ;
|
||||
Comment("Took a sell. stop loss: under current wick, " + "Active trade id: " + activeTradeId);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Comment("i cant take a trade because the arrray is full");
|
||||
}
|
||||
|
||||
|
||||
Comment(TimeToString(currTime,TIME_MINUTES) + ": price has reached the candle low, im taking a sell");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if(newCandleDetectorM1.isNewCandle())
|
||||
{
|
||||
|
||||
// BUY CASE
|
||||
if(waitForBottomWickToForm == true && wickLengthCounter < wickLengthInMinutes)
|
||||
{
|
||||
wickLengthCounter++ ;
|
||||
}
|
||||
|
||||
// SELL CASE
|
||||
|
||||
if(waitForTopWickToForm == true && wickLengthCounter < wickLengthInMinutes){
|
||||
wickLengthCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if(newCandleDetectorM15.isNewCandle())
|
||||
{
|
||||
|
||||
manageRiskIfNeeded();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
if(newCandleDetector30M.isNewCandle())
|
||||
{
|
||||
wickTradeTaken = false ;
|
||||
if(bottomWickFormed){ // reset the bottomWickFormed flag. this is for the cases that bottom wick has formed, but m30 candle closed and the trade still not taken
|
||||
bottomWickFormed = false ;
|
||||
buyStopPrice = -1;
|
||||
}
|
||||
|
||||
if(topWickFormed){ // reset the topWickFormed flag. this is for the cases that top wick has formed, but m30 candle closed and the trade still not taken
|
||||
topWickFormed = false ;
|
||||
sellStopPrice = -1;
|
||||
}
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_M30);
|
||||
|
||||
// DETECTING SUPPORTS AND RESISTANCES
|
||||
detectAndDrawResistanceOnTimeFrame(PERIOD_M30,"PERIOD_M30",clrPink,clrBlue,zoneContainer_M30);
|
||||
detectAndDrawSupportOnTimeFrame(PERIOD_M30,"PERIOD_M30",clrYellow,clrGreen,zoneContainerSupport_M30);
|
||||
|
||||
|
||||
// VARIABLE PREPROCESSING FOR BOS
|
||||
double brokenResistanceLowerPrice = -1 ;
|
||||
string brokenZoneTypeResistance = "" ;
|
||||
|
||||
double brokenSupportHigherPrice = -1;
|
||||
string brokenZoneTypeSupport = "" ;
|
||||
|
||||
|
||||
|
||||
|
||||
// BREAK OF STRUCTURE HANDLING
|
||||
|
||||
if(updateBreakAboveStructureAndDelete(zoneContainer_M30,PERIOD_M30,"PERIOD_M30",brokenResistanceLowerPrice,brokenZoneTypeResistance)
|
||||
&& buyBreakerCandleIsValid(PERIOD_M30, SIZE_OF_BREAKER_CANDLE_BODY)
|
||||
&& ((sessionIsNy() && TRADE_NEW_YORK_ALLOWED) || (sessionIsLondon() && TRADE_LONDON_ALLOWED)) && BUYS_ALLOWED) // means M30 candle broke structure, and the breaker candle is valid (big enough),and time is in the sessions (ny or london or both, based on what the user chose))
|
||||
{
|
||||
|
||||
|
||||
|
||||
double firstResistancePrice = findClosestResistancePrice(zoneContainer_M30);
|
||||
double cleanRangeValueBuys = firstResistancePrice - SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
|
||||
Print("first resistcane price is: "+ firstResistancePrice);
|
||||
if(zoneContainer_M30.getNumberOfActiveZones() > 0 && firstResistancePrice != -1 && brokenZoneTypeResistance == "TYPE_RESISTANCE_BREAKOUT")
|
||||
{
|
||||
|
||||
|
||||
Comment("Price Broke and closed above resistance zone, im waiting for a bottom wick to form");
|
||||
waitForBottomWickToForm = true ;
|
||||
|
||||
}
|
||||
|
||||
else if(zoneContainer_M30.getNumberOfActiveZones() == 0 && brokenZoneTypeResistance == "TYPE_RESISTANCE_BREAKOUT")
|
||||
{
|
||||
|
||||
|
||||
Comment("Price Broke and closed above resistance zone, im waiting for a bottom wick to form");
|
||||
waitForBottomWickToForm = true ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
if(updateBreakBelowStructureAndDelete(zoneContainerSupport_M30,PERIOD_M30,"PERIOD_M30",brokenSupportHigherPrice,brokenZoneTypeSupport)
|
||||
&& sellBreakerCandleIsValid(PERIOD_M30, SIZE_OF_BREAKER_CANDLE_BODY)
|
||||
&& ((sessionIsNy() && TRADE_NEW_YORK_ALLOWED) || (sessionIsLondon() && TRADE_LONDON_ALLOWED)) && SELLS_ALLOWED) // means M30 candle broke structure, and the breaker candle is valid (big enough),and time is in the sessions (ny or london or both, based on what the user chose))
|
||||
{
|
||||
|
||||
|
||||
double firstSupportPrice = findClosestSupportPrice(zoneContainerSupport_M30);
|
||||
double cleanRangeValueSells = SymbolInfoDouble(_Symbol, SYMBOL_BID) - firstSupportPrice;
|
||||
|
||||
if(zoneContainerSupport_M30.getNumberOfActiveZones() > 0 && firstSupportPrice != -1 && brokenZoneTypeSupport == "TYPE_SUPPORT_BREAKOUT")
|
||||
{
|
||||
waitForTopWickToForm = true ;
|
||||
Comment("Price Broke and closed below support zone, im waiting for a top wick to form");
|
||||
|
||||
|
||||
}
|
||||
|
||||
else if(zoneContainerSupport_M30.getNumberOfActiveZones() == 0 && brokenZoneTypeSupport == "TYPE_SUPPORT_BREAKOUT"){
|
||||
waitForTopWickToForm = true ;
|
||||
Comment("Price Broke and closed below support zone, im waiting for a top wick to form");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
datetime currTime = TimeCurrent();
|
||||
ObjectSetString(0,"clockTextTiger",OBJPROP_TEXT,TimeToString(currTime,TIME_MINUTES));
|
||||
|
||||
|
||||
zoneContainer_M30.printZonesSortedArray();
|
||||
zoneContainerSupport_M30.printZonesSortedArray();
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
if(newCandleDetectorDaily.isNewCandle())
|
||||
{
|
||||
|
||||
//detectAndDrawResistanceOnTimeFrame(PERIOD_D1,"PERIOD_D1",clrYellow,clrYellow,zoneContainer_D1);
|
||||
//updateBreakAboveStructureAndDelete(zoneContainer_D1,PERIOD_D1,"PERIOD_D1");
|
||||
objectsManager.drawVerticalLine(clrAqua, TimeCurrent());
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
if(newCandleDetectorWeekly.isNewCandle())
|
||||
{
|
||||
|
||||
objectsManager.drawVerticalLine(clrRed, TimeCurrent());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Timer function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTimer()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Trade function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTrade()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TradeTransaction function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTradeTransaction(const MqlTradeTransaction& trans,
|
||||
const MqlTradeRequest& request,
|
||||
const MqlTradeResult& result)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Tester function |
|
||||
//+------------------------------------------------------------------+
|
||||
double OnTester()
|
||||
{
|
||||
//---
|
||||
double ret=0.0;
|
||||
//---
|
||||
|
||||
//---
|
||||
return(ret);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterInit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterInit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterPass function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterPass()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterDeinit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterDeinit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnChartEvent(const int id,
|
||||
const long &lparam,
|
||||
const double &dparam,
|
||||
const string &sparam)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| BookEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnBookEvent(const string &symbol)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,423 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| TigerObserver.mq5 |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
|
||||
#include "Algo_Skeleton_Functions.mqh"
|
||||
|
||||
int OnInit()
|
||||
{
|
||||
//--- create timer
|
||||
EventSetTimer(60);
|
||||
|
||||
// ONLY FOR VISULAZITAION ON STRATEGY TESTER
|
||||
iClose(_Symbol,PERIOD_W1,1);
|
||||
iClose(_Symbol,PERIOD_D1,1);
|
||||
iClose(_Symbol,PERIOD_H4,5);
|
||||
iClose(_Symbol,PERIOD_H1,5);
|
||||
iClose(_Symbol,PERIOD_M30,5);
|
||||
iClose(_Symbol,PERIOD_M15,5);
|
||||
|
||||
objectsManager.addTextTiger();
|
||||
|
||||
for(int i=0; i<NUM_MAX_ALLOWED_TRADES ; i++)
|
||||
{
|
||||
BuyActiveTradesArray[i] = NULL ;
|
||||
SellActiveTradesArray[i] = NULL ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//objectsManager.addMarketDescriptionTextTiger();
|
||||
|
||||
//---
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- destroy timer
|
||||
Print("Buys Count: " + buysCount);
|
||||
Print("Sells Count: " + sellsCount);
|
||||
EventKillTimer();
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//---
|
||||
|
||||
cleanBuyTradesArr();
|
||||
cleanSellTradesArr();
|
||||
secureProfitIfNeeded();
|
||||
|
||||
if(newCandleDetectorM15.isNewCandle())
|
||||
{
|
||||
|
||||
manageRiskIfNeeded();
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
if(newCandleDetector30M.isNewCandle())
|
||||
{
|
||||
|
||||
//Print("zone coutner is: "+ zoneContainer_M30.getNumberOfActiveZones());
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_M30);
|
||||
//Print("number of opened orders are: " + PositionsTotal());
|
||||
// DETECTING SUPPORTS AND RESISTANCES
|
||||
detectAndDrawResistanceOnTimeFrame(PERIOD_M30,"PERIOD_M30",clrPink,clrBlue,zoneContainer_M30);
|
||||
detectAndDrawSupportOnTimeFrame(PERIOD_M30,"PERIOD_M30",clrYellow,clrGreen,zoneContainerSupport_M30);
|
||||
|
||||
|
||||
|
||||
// VARIABLE PREPROCESSING FOR BOS
|
||||
double brokenResistanceLowerPrice = -1 ;
|
||||
string brokenZoneTypeResistance = "" ;
|
||||
|
||||
double brokenSupportHigherPrice = -1;
|
||||
string brokenZoneTypeSupport = "" ;
|
||||
|
||||
// BREAK OF STRUCTURE HANDLING
|
||||
|
||||
if(updateBreakAboveStructureAndDelete(zoneContainer_M30,PERIOD_M30,"PERIOD_M30",brokenResistanceLowerPrice,brokenZoneTypeResistance)
|
||||
&& buyBreakerCandleIsValid(PERIOD_M30, SIZE_OF_BREAKER_CANDLE_BODY)
|
||||
&& ((sessionIsNy() && TRADE_NEW_YORK_ALLOWED) || (sessionIsLondon() && TRADE_LONDON_ALLOWED)) && BUYS_ALLOWED) // means M30 candle broke structure, and the breaker candle is valid (big enough),and time is in the sessions (ny or london or both, based on what the user chose))
|
||||
{
|
||||
|
||||
double firstResistancePrice = findClosestResistancePrice(zoneContainer_M30);
|
||||
double cleanRangeValueBuys = firstResistancePrice - SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
|
||||
|
||||
if(firstResistancePrice != -1 && brokenZoneTypeResistance == "TYPE_RESISTANCE_BREAKOUT")
|
||||
{
|
||||
Comment("M30 candle Broke and closed above the zone. the closest resistance price is:" + DoubleToString(firstResistancePrice));
|
||||
if(cleanRangeValueBuys >= cleanRangeUponEntry)
|
||||
{
|
||||
|
||||
double stopLossBased_H1 = iLow(_Symbol,PERIOD_H1,1);
|
||||
double stopLossBased_M30 = iLow(_Symbol,PERIOD_M30,1);
|
||||
double stopLossBased_M15 = iLow(_Symbol,PERIOD_M15,1);
|
||||
|
||||
stopLossBased_H1 = stopLossBased_H1 - stopLossUnderWickBy ;
|
||||
stopLossBased_M30 = stopLossBased_M30 - stopLossUnderWickBy ;
|
||||
stopLossBased_M15 = stopLossBased_M15 - stopLossUnderWickBy ;
|
||||
|
||||
if(stopLossIsValidBuys(stopLossBased_M30, maxPipsRiskAmount))
|
||||
{
|
||||
|
||||
double lotsToEnter = lsCalc.calculateLotSize(riskDollars,stopLossBased_M30);
|
||||
int indexToNewTrade ;
|
||||
if((indexToNewTrade = findAvailableSpotInBuyManagerArr()) != -1) // find a spot in the trades array, and save the result
|
||||
{
|
||||
Print("The free index found is: " + indexToNewTrade);
|
||||
activeTradeId = buyEntryManager.takeBuyTradeTiger(lotsToEnter,stopLossBased_M30) ;
|
||||
|
||||
BuyTradeManagerTiger* tempTigerManager= new BuyTradeManagerTiger(activeTradeId); // create an object of type buyTradeManagerTiger
|
||||
BuyActiveTradesArray[indexToNewTrade] = tempTigerManager ;// put the new object in the array
|
||||
buysCount++;
|
||||
|
||||
Comment("Took a buy. stop loss: based on M30, " + "Active trade id: " + activeTradeId);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Comment("I cant take a trade because the trades array is full");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
if(stopLossIsValidBuys(stopLossBased_M15,maxPipsRiskAmount) && candleClosedBullish(PERIOD_M15,1))
|
||||
{
|
||||
|
||||
double lotsToEnter = lsCalc.calculateLotSize(riskDollars,stopLossBased_M15);
|
||||
int indexToNewTrade ;
|
||||
if((indexToNewTrade = findAvailableSpotInBuyManagerArr()) != -1) // find a spot in the trades array, and save the result
|
||||
{
|
||||
Print("The free index found is: " + indexToNewTrade);
|
||||
activeTradeId = buyEntryManager.takeBuyTradeTiger(lotsToEnter,stopLossBased_M15) ;
|
||||
|
||||
BuyTradeManagerTiger* tempTigerManager= new BuyTradeManagerTiger(activeTradeId); // create an object of type buyTradeManagerTiger
|
||||
BuyActiveTradesArray[indexToNewTrade] = tempTigerManager ;// put the new object in the array
|
||||
buysCount++;
|
||||
Comment("Took a buy. stop loss: based on M15, " + "Active trade id: " + activeTradeId);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Comment("I cant take a trade because the trades array is full");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
Comment("Failed to find a valid stop loss on both M30 and M15 !");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
datetime currTime = TimeCurrent();
|
||||
string timeInStr = TimeToString(currTime,TIME_MINUTES);
|
||||
|
||||
Comment(timeInStr + ": Price Broke the resitance zone, but not enough clean range to take a trade");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
datetime currTime = TimeCurrent();
|
||||
string timeInStr = TimeToString(currTime,TIME_MINUTES);
|
||||
Comment(timeInStr+ ": Price broke the resistance zone but i dont see the next target zone, Or the zone price broke was not a breakout zone ");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(updateBreakBelowStructureAndDelete(zoneContainerSupport_M30,PERIOD_M30,"PERIOD_M30",brokenSupportHigherPrice,brokenZoneTypeSupport)
|
||||
&& sellBreakerCandleIsValid(PERIOD_M30, SIZE_OF_BREAKER_CANDLE_BODY)
|
||||
&& ((sessionIsNy() && TRADE_NEW_YORK_ALLOWED) || (sessionIsLondon() && TRADE_LONDON_ALLOWED)) && SELLS_ALLOWED) // means M30 candle broke structure, and the breaker candle is valid (big enough),and time is in the sessions (ny or london or both, based on what the user chose))
|
||||
{
|
||||
|
||||
|
||||
double firstSupportPrice = findClosestSupportPrice(zoneContainerSupport_M30);
|
||||
|
||||
double cleanRangeValueSells = SymbolInfoDouble(_Symbol, SYMBOL_BID) - firstSupportPrice;
|
||||
|
||||
Print("firstSupport variable is: " + firstSupportPrice);
|
||||
Print("cleanRangeValueSells :" + cleanRangeValueSells);
|
||||
|
||||
|
||||
if(firstSupportPrice != -1 && brokenZoneTypeSupport == "TYPE_SUPPORT_BREAKOUT")
|
||||
{
|
||||
Comment("M30 candle Broke and closed below the zone. the closest support price is:" + DoubleToString(firstSupportPrice));
|
||||
if(cleanRangeValueSells >= cleanRangeUponEntry)
|
||||
{
|
||||
|
||||
double stopLossBased_H1 = iHigh(_Symbol,PERIOD_H1,1);
|
||||
double stopLossBased_M30 = iHigh(_Symbol,PERIOD_M30,1);
|
||||
double stopLossBased_M15 = iHigh(_Symbol,PERIOD_M15,1);
|
||||
|
||||
stopLossBased_H1 = stopLossBased_H1 + stopLossAboveWickBy ;
|
||||
stopLossBased_M30 = stopLossBased_M30 + stopLossAboveWickBy ;
|
||||
stopLossBased_M15 = stopLossBased_M15 + stopLossAboveWickBy ;
|
||||
|
||||
if(stopLossIsValidSells(stopLossBased_M30, maxPipsRiskAmount))
|
||||
{
|
||||
|
||||
double lotsToEnter = lsCalc.calculateLotSize(riskDollars,stopLossBased_M30);
|
||||
int indexToNewTrade ;
|
||||
|
||||
if((indexToNewTrade = findAvailableSpotInSellManagerArr()) != -1)
|
||||
{
|
||||
|
||||
Print("The free index found is: " + indexToNewTrade);
|
||||
activeTradeId = sellEntryManager.takeSellTradeTiger(lotsToEnter,stopLossBased_M30) ;
|
||||
|
||||
SellTradeManagerTiger* tempTigerManager= new SellTradeManagerTiger(activeTradeId); // create an object of type sellTradeManagerTiger
|
||||
SellActiveTradesArray[indexToNewTrade] = tempTigerManager ;// put the new object in the array
|
||||
sellsCount++;
|
||||
Comment("Took a sell. stop loss: based on M30, " + "Active trade id: " + activeTradeId);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Comment("i cant take a trade because the arrray is full");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
if(stopLossIsValidSells(stopLossBased_M15,maxPipsRiskAmount) && candleClosedBearish(PERIOD_M15,1))
|
||||
{
|
||||
double lotsToEnter = lsCalc.calculateLotSize(riskDollars,stopLossBased_M15);
|
||||
int indexToNewTrade ;
|
||||
if((indexToNewTrade = findAvailableSpotInSellManagerArr()) != -1)
|
||||
{
|
||||
Print("The free index found is: " + indexToNewTrade);
|
||||
activeTradeId = sellEntryManager.takeSellTradeTiger(lotsToEnter,stopLossBased_M15) ;
|
||||
|
||||
SellTradeManagerTiger* tempTigerManager= new SellTradeManagerTiger(activeTradeId); // create an object of type buyTradeManagerTiger
|
||||
SellActiveTradesArray[indexToNewTrade] = tempTigerManager ;// put the new object in the array
|
||||
sellsCount++;
|
||||
Comment("Took a sell. stop loss: based on M15, "+ "Active trade id: " + activeTradeId);
|
||||
}
|
||||
else
|
||||
{
|
||||
Comment("i cant take a trade since another one is running");
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
Comment("Failed to find a valid stop loss on both M30 and M15 !");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
datetime currTime = TimeCurrent();
|
||||
string timeInStr = TimeToString(currTime,TIME_MINUTES);
|
||||
|
||||
|
||||
Comment(timeInStr + ": Price Broke the support zone, but not enough clean range to take a trade");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
datetime currTime = TimeCurrent();
|
||||
string timeInStr = TimeToString(currTime,TIME_MINUTES);
|
||||
Comment(timeInStr+ ": Price broke the support zone but i dont see the next target zone, Or the zone price broke was not a breakout zone ");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
datetime currTime = TimeCurrent();
|
||||
ObjectSetString(0,"clockTextTiger",OBJPROP_TEXT,TimeToString(currTime,TIME_MINUTES));
|
||||
|
||||
|
||||
zoneContainer_M30.printZonesSortedArray();
|
||||
zoneContainerSupport_M30.printZonesSortedArray();
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
if(newCandleDetectorDaily.isNewCandle())
|
||||
{
|
||||
|
||||
//detectAndDrawResistanceOnTimeFrame(PERIOD_D1,"PERIOD_D1",clrYellow,clrYellow,zoneContainer_D1);
|
||||
//updateBreakAboveStructureAndDelete(zoneContainer_D1,PERIOD_D1,"PERIOD_D1");
|
||||
objectsManager.drawVerticalLine(clrAqua, TimeCurrent());
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
if(newCandleDetectorWeekly.isNewCandle())
|
||||
{
|
||||
|
||||
objectsManager.drawVerticalLine(clrRed, TimeCurrent());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Timer function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTimer()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Trade function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTrade()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TradeTransaction function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTradeTransaction(const MqlTradeTransaction& trans,
|
||||
const MqlTradeRequest& request,
|
||||
const MqlTradeResult& result)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Tester function |
|
||||
//+------------------------------------------------------------------+
|
||||
double OnTester()
|
||||
{
|
||||
//---
|
||||
double ret=0.0;
|
||||
//---
|
||||
|
||||
//---
|
||||
return(ret);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterInit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterInit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterPass function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterPass()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterDeinit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterDeinit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnChartEvent(const int id,
|
||||
const long &lparam,
|
||||
const double &dparam,
|
||||
const string &sparam)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| BookEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnBookEvent(const string &symbol)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,232 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| TigerObserver.mq5 |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
|
||||
#include "Algo_Skeleton_Functions.mqh"
|
||||
|
||||
int OnInit()
|
||||
{
|
||||
//--- create timer
|
||||
EventSetTimer(60);
|
||||
|
||||
// ONLY FOR VISULAZITAION ON STRATEGY TESTER
|
||||
iClose(_Symbol,PERIOD_W1,1);
|
||||
iClose(_Symbol,PERIOD_D1,1);
|
||||
iClose(_Symbol,PERIOD_H4,5);
|
||||
iClose(_Symbol,PERIOD_H1,5);
|
||||
iClose(_Symbol,PERIOD_M30,5);
|
||||
iClose(_Symbol,PERIOD_M15,5);
|
||||
|
||||
|
||||
|
||||
objectsManager.addTextTiger();
|
||||
|
||||
for(int i=0; i<NUM_MAX_ALLOWED_TRADES ; i++)
|
||||
{
|
||||
BuyActiveTradesArray[i] = NULL ;
|
||||
SellActiveTradesArray[i] = NULL ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//objectsManager.addMarketDescriptionTextTiger();
|
||||
|
||||
//---
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- destroy timer
|
||||
Print("Buys Count: " + buysCount);
|
||||
Print("Sells Count: " + sellsCount);
|
||||
EventKillTimer();
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//---
|
||||
|
||||
cleanBuyTradesArr();
|
||||
cleanSellTradesArr();
|
||||
secureProfitIfNeeded();
|
||||
|
||||
/*if(newCandleDetectorM15.isNewCandle())
|
||||
{
|
||||
|
||||
|
||||
} */
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
if(newCandleDetector30M.isNewCandle())
|
||||
{
|
||||
|
||||
datetime currTime = TimeCurrent();
|
||||
ObjectSetString(0,"clockTextTiger",OBJPROP_TEXT,TimeToString(currTime,TIME_MINUTES));
|
||||
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
if(newCandleDetector1H.isNewCandle()){
|
||||
|
||||
if(zoneContainerSupport_H4.getNumberOfActiveZones()>0){
|
||||
updateNormalZonesSupport(zoneContainerSupport_H4,PERIOD_H4,"PERIOD_H4",clrAliceBlue,rangeDistanceBetweenZonesActual_H4);
|
||||
}
|
||||
|
||||
if(zoneContainer_H4.getNumberOfActiveZones()){
|
||||
updateNormalZonesResistance(zoneContainer_H4,PERIOD_H4,"PERIOD_H4",clrPink,rangeDistanceBetweenZonesActual_H4);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(newCandleDetector4H.isNewCandle()){
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_H4);
|
||||
|
||||
detectAndDrawResistanceOnTimeFrame(PERIOD_H4,"PERIOD_H4",clrPink,zoneContainer_H4,rangeDistanceBetweenZonesActual_H4);
|
||||
detectAndDrawSupportOnTimeFrame(PERIOD_H4,"PERIOD_H4",clrAliceBlue,zoneContainerSupport_H4,rangeDistanceBetweenZonesActual_H4);
|
||||
|
||||
// BREAK OF STRUCTURE HANDLING
|
||||
handleBuys(zoneContainer_H4,PERIOD_H4,"PERIOD_H4",cleanRangeUponEntryActual);
|
||||
handleSells(zoneContainerSupport_H4,PERIOD_H4,"PERIOD_H4",cleanRangeUponEntryActual);
|
||||
|
||||
|
||||
zoneContainerSupport_H4.printZonesSortedArray();
|
||||
zoneContainer_H4.printZonesSortedArray();
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(newCandleDetectorDaily.isNewCandle())
|
||||
{
|
||||
|
||||
//detectAndDrawResistanceOnTimeFrame(PERIOD_D1,"PERIOD_D1",clrYellow,clrYellow,zoneContainer_D1);
|
||||
//updateBreakAboveStructureAndDelete(zoneContainer_D1,PERIOD_D1,"PERIOD_D1");
|
||||
objectsManager.drawVerticalLine(clrAqua, TimeCurrent());
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
if(newCandleDetectorWeekly.isNewCandle())
|
||||
{
|
||||
|
||||
objectsManager.drawVerticalLine(clrRed, TimeCurrent());
|
||||
|
||||
weekCounter++ ;
|
||||
|
||||
if(weekCounter == deleteAllZonesAfter_Weeks){
|
||||
|
||||
//deleteAllzonesWithGUI();
|
||||
weekCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Timer function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTimer()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Trade function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTrade()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TradeTransaction function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTradeTransaction(const MqlTradeTransaction& trans,
|
||||
const MqlTradeRequest& request,
|
||||
const MqlTradeResult& result)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Tester function |
|
||||
//+------------------------------------------------------------------+
|
||||
double OnTester()
|
||||
{
|
||||
//---
|
||||
double ret=0.0;
|
||||
//---
|
||||
|
||||
//---
|
||||
return(ret);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterInit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterInit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterPass function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterPass()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterDeinit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterDeinit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnChartEvent(const int id,
|
||||
const long &lparam,
|
||||
const double &dparam,
|
||||
const string &sparam)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| BookEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnBookEvent(const string &symbol)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,182 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| TrendBreakouts.mq5 |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
|
||||
#define NUM_WEEKS_RESEARCH 48
|
||||
#include "Algo_Skeleton_Functions.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int bullishCandlesCount = 0 ;
|
||||
int conditionMetBullish = 0 ;
|
||||
int secondConditionMetBullish = 0;
|
||||
int bearishCandlesCount = 0;
|
||||
int conditionMetBearish = 0 ;
|
||||
int secondConditionMetBearish = 0 ;
|
||||
|
||||
input group "Conditions"
|
||||
input bool firstCondition = false ;
|
||||
input bool secondCondition = false ;
|
||||
input bool noCondition = false ;
|
||||
|
||||
int OnInit()
|
||||
{
|
||||
//---
|
||||
|
||||
//---
|
||||
/* string fileName = "First_Condition_Bullish.csv" ; // if you want to find the csv file, go to file -> open data folder -> mql5 -> files . all from the visual mode
|
||||
int fileHandle = FileOpen(fileName,FILE_READ|FILE_WRITE |FILE_CSV|FILE_ANSI);
|
||||
|
||||
FileSeek(fileHandle,0,SEEK_END);
|
||||
FileWrite(fileHandle,"-----","Size of Week 1","Size of Week 2", "Monday", "Tuesday","Wednesday","Thursday","Friday","Retracement Measure","Low below previous close","Day of lowest point"); */
|
||||
|
||||
|
||||
string fileName1 = "First_Condition_Bearish.csv" ; // if you want to find the csv file, go to file -> open data folder -> mql5 -> files . all from the visual mode
|
||||
int fileHandle1 = FileOpen(fileName1,FILE_READ|FILE_WRITE |FILE_CSV|FILE_ANSI);
|
||||
|
||||
FileSeek(fileHandle1,0,SEEK_END);
|
||||
FileWrite(fileHandle1,"-----","Size of Week 1","Size of Week 2", "Monday", "Tuesday","Wednesday","Thursday","Friday","Retracement Measure","High above previous close","Day of Highest point");
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//---
|
||||
Print("Count: "+ bullishCandlesCount + " First Condition: " + conditionMetBullish + " Second Condition: " + secondConditionMetBullish);
|
||||
Print("Count: "+ bearishCandlesCount + " First Condition: " + conditionMetBearish + " Second Condition: " + secondConditionMetBearish);
|
||||
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//---
|
||||
|
||||
|
||||
|
||||
if(newCandleDetectorDaily.isNewCandle())
|
||||
{
|
||||
//objectsManager.drawVerticalLine(clrAliceBlue, TimeCurrent());
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
int shift = 2 ;
|
||||
if(newCandleDetectorWeekly.isNewCandle())
|
||||
{
|
||||
objectsManager.drawVerticalLine(clrRed, TimeCurrent());
|
||||
|
||||
if(candleClosedBullish(PERIOD_W1,shift))
|
||||
{
|
||||
if(!bullishCandleIsWeak(PERIOD_W1,shift,WICK_RATIO_REJECTION))
|
||||
{
|
||||
|
||||
bullishCandlesCount++ ;
|
||||
|
||||
if(firstCondition){
|
||||
if((iHigh(_Symbol,PERIOD_W1,1) > iHigh(_Symbol,PERIOD_W1,2)) && (iLow(_Symbol,PERIOD_W1,1) >iLow(_Symbol,PERIOD_W1,2)))
|
||||
{
|
||||
saveInCsv("firstCondition_Bullish.csv");
|
||||
conditionMetBullish++ ;
|
||||
}
|
||||
}
|
||||
|
||||
if(secondCondition){
|
||||
if((iHigh(_Symbol,PERIOD_W1,1) > iClose(_Symbol,PERIOD_W1,2)) && (iLow(_Symbol,PERIOD_W1,1) > iLow(_Symbol,PERIOD_W1,2)))
|
||||
{
|
||||
saveInCsv("secondCondition_Bullish.csv");
|
||||
secondConditionMetBullish++ ;
|
||||
}
|
||||
}
|
||||
|
||||
if(noCondition){
|
||||
saveInCsv("noCondition_Bullish.csv");
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(candleClosedBearish(PERIOD_W1,shift))
|
||||
{
|
||||
|
||||
if(!bearishCandleIsWeak(PERIOD_W1,shift,WICK_RATIO_REJECTION))
|
||||
{
|
||||
|
||||
bearishCandlesCount++ ;
|
||||
if((iLow(_Symbol,PERIOD_W1,1) < iLow(_Symbol,PERIOD_W1,2)) && (iHigh(_Symbol,PERIOD_W1,1) < iHigh(_Symbol,PERIOD_W1,2)))
|
||||
{
|
||||
conditionMetBearish++ ;
|
||||
}
|
||||
|
||||
|
||||
if((iLow(_Symbol,PERIOD_W1,1) < iClose(_Symbol,PERIOD_W1,2)) && (iHigh(_Symbol,PERIOD_W1,1) < iHigh(_Symbol,PERIOD_W1,2)))
|
||||
{
|
||||
secondConditionMetBearish++ ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Print("bearish candles count: " + bearishCandlesCount);
|
||||
//Print("bullish canldes count: " + bullishCandlesCount);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
void saveInCsv(string csvFileName){
|
||||
int lastWeekDaysArr[5] ;
|
||||
for(int i=0; i<5; i++)
|
||||
{
|
||||
lastWeekDaysArr[i]= -1;
|
||||
}
|
||||
for(int i=5 ; i>0 ; i--)
|
||||
{
|
||||
if(candleClosedBullish(PERIOD_D1,i))
|
||||
{
|
||||
lastWeekDaysArr[5-i] = 1 ;
|
||||
}
|
||||
if(candleClosedBearish(PERIOD_D1,i))
|
||||
{
|
||||
lastWeekDaysArr[5-i] = 0 ;
|
||||
}
|
||||
}
|
||||
|
||||
double firstWeekSize = iHigh(_Symbol,PERIOD_W1,2) - iLow(_Symbol,PERIOD_W1,2) ;
|
||||
double secondWeekSize = iHigh(_Symbol,PERIOD_W1,1) - iLow(_Symbol,PERIOD_W1,1) ;
|
||||
|
||||
|
||||
datetime time = iTime(_Symbol,PERIOD_W1,2);
|
||||
string timeInStr = TimeToString(time,TIME_DATE);
|
||||
|
||||
string fileName = csvFileName ; // if you want to find the csv file, go to file -> open data folder -> mql5 -> files . all from the visual mode
|
||||
int fileHandle = FileOpen(fileName,FILE_READ|FILE_WRITE/* |FILE_CSV|FILE_ANSI*/);
|
||||
|
||||
|
||||
|
||||
FileSeek(fileHandle,0,SEEK_END);
|
||||
FileWrite(fileHandle,timeInStr,firstWeekSize,secondWeekSize,lastWeekDaysArr[0],lastWeekDaysArr[1],lastWeekDaysArr[2],lastWeekDaysArr[3],lastWeekDaysArr[4]);
|
||||
|
||||
FileClose(fileHandle);
|
||||
}
|
||||
@@ -0,0 +1,341 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Zone.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#include "LowFractal.mqh"
|
||||
#include "HighFractal.mqh"
|
||||
#include "BuyEntryManager.mqh"
|
||||
#include "SellEntryManager.mqh"
|
||||
#include "BuyTradeManager.mqh"
|
||||
#include "SellTradeManager.mqh"
|
||||
|
||||
#define SIZE_ATTACHED_FRACTALS
|
||||
#define TP_ARR_SIZE 3
|
||||
class Zone
|
||||
{
|
||||
private:
|
||||
string id ;
|
||||
string timeFrame ;
|
||||
string type ; // has 2 types : TYPE_SUPPORT, TYPE_RESISTANCE
|
||||
string state ; // state is one of 5 states : STATE_CLEAN , STATE_TESTED, STATE_BROKEN, STATE_BROKEN_RETESTED, STATE_WAITING(used when price breaks structure, and is waiting to confirm BOS or a liquidity sweep)
|
||||
datetime leftEdge ;
|
||||
datetime rightEdge;
|
||||
double lowerEdgePrice ;
|
||||
double higherEdgePrice ;
|
||||
double stopLossPrice ;
|
||||
double tpPrices[TP_ARR_SIZE] ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public:
|
||||
Zone();
|
||||
Zone:: Zone(string _zoneId,double _higherEdgePrice,double _lowerEdgePrice,datetime _leftEdge,datetime _rightEdge,string _timeFrameStr,string _type);
|
||||
~Zone();
|
||||
BuyEntryManager* buyEntryManager ;
|
||||
BuyTradeManager* buyTradeManager;
|
||||
|
||||
SellEntryManager* sellEntryManager ;
|
||||
SellTradeManager* sellTradeManager ;
|
||||
|
||||
|
||||
|
||||
// GETTERS
|
||||
double getHigherEdge();
|
||||
double getLowerEdge();
|
||||
datetime getLeftEdge();
|
||||
datetime getRightEdge();
|
||||
string getId();
|
||||
string getTimeFrame();
|
||||
string getState();
|
||||
string getType();
|
||||
double getStopLossPrice();
|
||||
double getZoneHeight();
|
||||
|
||||
|
||||
// SETTERS
|
||||
void setLeftEdge(datetime _leftEdge);
|
||||
void setRightEdge(datetime _rightEdge);
|
||||
void setLowerEdgePrice(double _lowerPirce);
|
||||
void setHigherEdgePrice(double _higherPrice);
|
||||
void setTimeFrame(string _timeframe);
|
||||
void setId(string _id);
|
||||
void setType(string _type);
|
||||
void setState(string _state);
|
||||
void setStopLossPrice(double slPrice);
|
||||
bool setTakeProfit(double tpVal); // returns false if there is no valid slot in the tp's array, and true on success
|
||||
|
||||
|
||||
// OTHER FUNCTIONS
|
||||
void printTpLevels();
|
||||
void printTradeManagerData();
|
||||
|
||||
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
Zone:: Zone()
|
||||
{
|
||||
|
||||
buyEntryManager = new BuyEntryManager();
|
||||
buyTradeManager = new BuyTradeManager();
|
||||
sellEntryManager = new SellEntryManager();
|
||||
sellTradeManager = new SellTradeManager();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for(int i=0 ;i< TP_ARR_SIZE ;i++){ // initialize the tp array with -1's
|
||||
tpPrices[i] = -1 ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Zone:: Zone(string _zoneId,double _higherEdgePrice,double _lowerEdgePrice,datetime _leftEdge,datetime _rightEdge,string _timeFrameStr,string _type){
|
||||
|
||||
buyEntryManager = new BuyEntryManager();
|
||||
buyTradeManager = new BuyTradeManager();
|
||||
sellEntryManager = new SellEntryManager();
|
||||
sellTradeManager = new SellTradeManager();
|
||||
|
||||
id = _zoneId ;
|
||||
|
||||
timeFrame = _timeFrameStr;
|
||||
type = _type; // has 2 types : TYPE_SUPPORT, TYPE_RESISTANCE
|
||||
leftEdge = _leftEdge;
|
||||
rightEdge = _rightEdge;
|
||||
lowerEdgePrice = _lowerEdgePrice;
|
||||
higherEdgePrice = _higherEdgePrice;
|
||||
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
Zone::~Zone()
|
||||
{
|
||||
delete buyEntryManager;
|
||||
delete sellEntryManager;
|
||||
delete buyTradeManager;
|
||||
delete sellTradeManager;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
// GETTERS
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
datetime Zone:: getLeftEdge()
|
||||
{
|
||||
|
||||
return leftEdge;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
datetime Zone:: getRightEdge()
|
||||
{
|
||||
|
||||
return rightEdge ;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double Zone:: getHigherEdge()
|
||||
{
|
||||
|
||||
return higherEdgePrice;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double Zone:: getLowerEdge()
|
||||
{
|
||||
|
||||
return lowerEdgePrice;
|
||||
}
|
||||
|
||||
string Zone :: getState(){
|
||||
|
||||
return state ;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
string Zone:: getId()
|
||||
{
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
string Zone:: getTimeFrame() {return timeFrame ;}
|
||||
|
||||
|
||||
|
||||
string Zone:: getType(){
|
||||
|
||||
return type ;
|
||||
}
|
||||
|
||||
|
||||
double Zone :: getStopLossPrice(){
|
||||
return stopLossPrice ;
|
||||
}
|
||||
|
||||
// SETTERS
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void Zone:: setLeftEdge(datetime _leftEdge)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void Zone:: setRightEdge(datetime _rightEdge)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void Zone:: setTimeFrame(string _timeframe)
|
||||
{
|
||||
|
||||
timeFrame = _timeframe;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void Zone:: setLowerEdgePrice(double _lowerPirce)
|
||||
{
|
||||
|
||||
lowerEdgePrice = _lowerPirce;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void Zone::setHigherEdgePrice(double _higherPrice)
|
||||
{
|
||||
|
||||
higherEdgePrice = _higherPrice ;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void Zone:: setId(string _id)
|
||||
{
|
||||
|
||||
id = _id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Zone:: setType(string _type){
|
||||
|
||||
type = _type ;
|
||||
}
|
||||
|
||||
|
||||
void Zone:: setState(string _state){
|
||||
|
||||
state = _state ;
|
||||
}
|
||||
|
||||
|
||||
void Zone:: setStopLossPrice(double slPrice){
|
||||
|
||||
stopLossPrice = slPrice ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool Zone:: setTakeProfit(double tpVal){
|
||||
for(int i=0; i<TP_ARR_SIZE; i++){
|
||||
if(tpPrices[i] == -1){
|
||||
tpPrices[i] = tpVal ;
|
||||
if(type == "TYPE_SUPPORT"){
|
||||
buyTradeManager.tpArray[i] = tpVal;
|
||||
}
|
||||
else if(type == "TYPE_RESISTANCE"){
|
||||
sellTradeManager.tpArray[i] = tpVal ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// GUI FUNCTIONS
|
||||
|
||||
|
||||
|
||||
|
||||
// ALGORITHM FUNCTIONS
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
void Zone:: printTpLevels(){
|
||||
|
||||
Print("Take Profit Levels are: ");
|
||||
for(int i=0 ; i< TP_ARR_SIZE;i++){
|
||||
if(tpPrices[i] != -1){
|
||||
Print(tpPrices[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double Zone:: getZoneHeight(){
|
||||
|
||||
return higherEdgePrice - lowerEdgePrice ;
|
||||
}
|
||||
|
||||
|
||||
void Zone:: printTradeManagerData(){
|
||||
|
||||
|
||||
if(type == "TYPE_SUPPORT"){
|
||||
Print("TP array in buyTradeManager is: ");
|
||||
for(int i=0;i<3;i++){
|
||||
Print("TP " + i + ": " + buyTradeManager.tpArray[i]);
|
||||
}
|
||||
}
|
||||
else if(type == "TYPE_RESISTANCE"){
|
||||
Print("TP array in sellTradeManager is: ");
|
||||
for(int i=0;i<3;i++){
|
||||
Print("TP " + i + ": " + sellTradeManager.tpArray[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,686 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ZoneContainer.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#include "Zone.mqh"
|
||||
#define ZONES_SORTED_ARR_SIZE 400
|
||||
class ZoneContainer
|
||||
{
|
||||
private:
|
||||
int zonesIdCounter ; // number to identify each zone when we create it, it keeps adding up. if we delete a zone, we dont decrement it
|
||||
int zonesIdCounterSupport ; // used for support zones. i had to make it different from the resistance because there was a problem of collision of id's between supports and resistances zones
|
||||
int numberOfActiveZones ;
|
||||
|
||||
Zone* zonesSortedArray[ZONES_SORTED_ARR_SIZE] ;
|
||||
int pivotEdges[2] ; // this array contains the indexes of the 2 zones that are closest to the current price , pivotEdges[0] = index of lower edge, pivotEdges[1] = index of higher edge
|
||||
public:
|
||||
ZoneContainer();
|
||||
~ZoneContainer();
|
||||
|
||||
// GETTERS
|
||||
int getZonesIdCounter();
|
||||
int getSupportZonesIdCounter();
|
||||
int getNumberOfActiveZones();
|
||||
|
||||
int getLowZonePivot();
|
||||
int getHighZonePivot();
|
||||
|
||||
// SETTERS
|
||||
|
||||
// OTHER FUNCTIONS
|
||||
void incrementZonesIdCounter();
|
||||
void incrementZonesIdCounterSupport();
|
||||
int addZone(Zone* _newZone);
|
||||
void addResistanceZoneTiger(Zone* _newZone);
|
||||
void addSupportZoneTiger(Zone* _newZone);
|
||||
void addHistoryResistanceZoneOnTop(Zone* _newZone);
|
||||
void addHistorySupportZoneAtBottom(Zone* _newZone);
|
||||
|
||||
|
||||
int updateZone(Zone* _tempZone,string _idOfOriginalZone);
|
||||
int deleteZone(string ID);
|
||||
void freeZonesSortedArray();
|
||||
void printZonesSortedArray();
|
||||
void forwardShiftZonesSortedArrayFromIndex(int _index);
|
||||
void backwardShiftZonesSortedArrayFromIndex(int _index);
|
||||
|
||||
void findOrUpdatePivotEdgesOnConfirm(double _ask, double _bid);
|
||||
void findOrUpdatePivotEdgesOnDelete();
|
||||
void printPivotEdges();
|
||||
Zone* getLowerPivotIndexZone();
|
||||
Zone* getHigherPivotIndexZone();
|
||||
|
||||
int getZoneIndex(string _id); // returns the index of the zone in the zonesSortedArray if it was found , and returns -1 if it wasnt found
|
||||
int searchForTheRightPlace(Zone* _zone);
|
||||
Zone* searchZoneById(string _idOfZone);
|
||||
Zone* getZoneByIndex(int _index);
|
||||
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
ZoneContainer::ZoneContainer()
|
||||
{
|
||||
zonesIdCounter = 0;
|
||||
zonesIdCounterSupport = 100 ;
|
||||
pivotEdges[0] = -1;
|
||||
pivotEdges[1] = -1;
|
||||
numberOfActiveZones = 0;
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
ZoneContainer::~ZoneContainer()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
// GETTERS
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int ZoneContainer:: getZonesIdCounter()
|
||||
{
|
||||
return zonesIdCounter;
|
||||
}
|
||||
|
||||
|
||||
int ZoneContainer:: getSupportZonesIdCounter(){
|
||||
|
||||
return zonesIdCounterSupport;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int ZoneContainer:: getNumberOfActiveZones()
|
||||
{
|
||||
|
||||
return numberOfActiveZones;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int ZoneContainer:: getLowZonePivot()
|
||||
{
|
||||
|
||||
return pivotEdges[0];
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int ZoneContainer:: getHighZonePivot()
|
||||
{
|
||||
|
||||
return pivotEdges[1] ;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
Zone* ZoneContainer:: getZoneByIndex(int _index)
|
||||
{
|
||||
|
||||
|
||||
|
||||
return zonesSortedArray[_index];
|
||||
|
||||
|
||||
|
||||
}
|
||||
// SETTERS
|
||||
|
||||
|
||||
// OTHER FUNCTIONS
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void ZoneContainer:: incrementZonesIdCounter()
|
||||
{
|
||||
zonesIdCounter++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ZoneContainer:: incrementZonesIdCounterSupport(){
|
||||
|
||||
zonesIdCounterSupport++ ;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int ZoneContainer:: addZone(Zone* _newZone)
|
||||
{
|
||||
int result = -1;
|
||||
if(numberOfActiveZones == 0) // means the array is empty
|
||||
{
|
||||
zonesSortedArray[0] = _newZone;
|
||||
numberOfActiveZones++;
|
||||
|
||||
return 1 ;
|
||||
}
|
||||
else
|
||||
if(_newZone.getHigherEdge() < zonesSortedArray[0].getLowerEdge()) // in this case the new zone should be put in the first place in the array
|
||||
{
|
||||
forwardShiftZonesSortedArrayFromIndex(0); // shift all the array
|
||||
zonesSortedArray[0] = _newZone ;
|
||||
numberOfActiveZones++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
if(_newZone.getLowerEdge() > zonesSortedArray[numberOfActiveZones-1].getHigherEdge()) // in this case the new zone should be in the last place in the array
|
||||
{
|
||||
zonesSortedArray[numberOfActiveZones] = _newZone;
|
||||
numberOfActiveZones++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else // in this case, the new zone sits somewhere in the array (not the edges)
|
||||
{
|
||||
int indexOfNewZone = searchForTheRightPlace(_newZone);
|
||||
if(indexOfNewZone != -1) // means found a place for the new zone
|
||||
{
|
||||
forwardShiftZonesSortedArrayFromIndex(indexOfNewZone);
|
||||
zonesSortedArray[indexOfNewZone] = _newZone ;
|
||||
numberOfActiveZones++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int ZoneContainer:: deleteZone(string ID)
|
||||
{
|
||||
|
||||
// 1. find the index of the zone with the ID
|
||||
int indexOfZoneToDelete = getZoneIndex(ID);
|
||||
if(indexOfZoneToDelete == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
if(indexOfZoneToDelete == (numberOfActiveZones-1)) // means that this is the last zone in the sorted array
|
||||
{
|
||||
// 2. delete the zone
|
||||
// 3. its the last element so do nothing
|
||||
delete zonesSortedArray[numberOfActiveZones-1] ;
|
||||
numberOfActiveZones--;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 2. delete the zone
|
||||
// 3. its not the last element, so shift the array 1 step backwards
|
||||
delete zonesSortedArray[indexOfZoneToDelete];
|
||||
backwardShiftZonesSortedArrayFromIndex(indexOfZoneToDelete);
|
||||
numberOfActiveZones--;
|
||||
return 1;
|
||||
}
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* int ZoneContainer:: deleteZoneTiger(string ID){
|
||||
|
||||
// 1. find the index of the zone with the ID
|
||||
int indexOfZoneToDelete = getZoneIndex(ID);
|
||||
if(indexOfZoneToDelete == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
if(indexOfZoneToDelete == (numberOfActiveZones-1)) // means that this is the last zone in the sorted array
|
||||
{
|
||||
// 2. delete the zone
|
||||
// 3. its the last element so do nothing
|
||||
delete zonesSortedArray[numberOfActiveZones-1] ;
|
||||
numberOfActiveZones--;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 2. delete the zone
|
||||
// 3. its not the last element, so shift the array 1 step backwards
|
||||
delete zonesSortedArray[indexOfZoneToDelete];
|
||||
backwardShiftZonesSortedArrayFromIndex(indexOfZoneToDelete);
|
||||
numberOfActiveZones--;
|
||||
return 1;
|
||||
}
|
||||
return 0 ;
|
||||
|
||||
|
||||
|
||||
|
||||
} */
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void ZoneContainer:: freeZonesSortedArray()
|
||||
{
|
||||
|
||||
for(int i=0; i<numberOfActiveZones; i++)
|
||||
{
|
||||
delete zonesSortedArray[i];
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void ZoneContainer::printZonesSortedArray()
|
||||
{
|
||||
if(numberOfActiveZones > 0)
|
||||
{
|
||||
for(int i=0; i<numberOfActiveZones; i++)
|
||||
{
|
||||
Print("Zone "+ i + ": " + "Type: " + zonesSortedArray[i].getType() + ", Lower Edge: " + zonesSortedArray[i].getLowerEdge() + " Higher Edge: "+ zonesSortedArray[i].getHigherEdge() + " Stop Loss Price: " + zonesSortedArray[i].getStopLossPrice());
|
||||
//zonesSortedArray[i].printTpLevels();
|
||||
//zonesSortedArray[i].printTradeManagerData();
|
||||
}
|
||||
|
||||
|
||||
Print("Current Price is between zone " + pivotEdges[0] + " and zone "+ pivotEdges[1]);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("There is no active zones !");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int ZoneContainer:: getZoneIndex(string _id)
|
||||
{
|
||||
int indexOfZone = -1;
|
||||
for(int i=0 ; i <numberOfActiveZones ; i++)
|
||||
{
|
||||
if(zonesSortedArray[i].getId() == _id)
|
||||
{
|
||||
indexOfZone = i ;
|
||||
return indexOfZone ;
|
||||
}
|
||||
}
|
||||
return indexOfZone ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void ZoneContainer::forwardShiftZonesSortedArrayFromIndex(int _index) // used for adding
|
||||
{
|
||||
|
||||
for(int x = numberOfActiveZones ; x > _index ; x--)
|
||||
{
|
||||
zonesSortedArray[x] = zonesSortedArray[x-1] ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void ZoneContainer:: backwardShiftZonesSortedArrayFromIndex(int _index) // used for deleting
|
||||
{
|
||||
for(int i= _index ; i<numberOfActiveZones ; i++)
|
||||
{
|
||||
zonesSortedArray[i] = zonesSortedArray[i+1];
|
||||
}
|
||||
zonesSortedArray[numberOfActiveZones-1] = NULL ; // empty the last element in the sorted array
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int ZoneContainer:: searchForTheRightPlace(Zone* _zone)
|
||||
{
|
||||
int index = -1;
|
||||
for(int i=0; i<numberOfActiveZones-1; i++)
|
||||
{
|
||||
if((_zone.getLowerEdge() > zonesSortedArray[i].getHigherEdge()) && (_zone.getHigherEdge() < zonesSortedArray[i+1].getLowerEdge()))
|
||||
{
|
||||
index = i+1;
|
||||
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return index ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int ZoneContainer :: updateZone(Zone* _tempZone, string _idOfOriginalZone)
|
||||
{
|
||||
|
||||
|
||||
Zone* zoneToUpdate = searchZoneById(_idOfOriginalZone);
|
||||
|
||||
zoneToUpdate.setHigherEdgePrice(_tempZone.getHigherEdge());
|
||||
zoneToUpdate.setLowerEdgePrice(_tempZone.getLowerEdge());
|
||||
zoneToUpdate.setLeftEdge(_tempZone.getLeftEdge());
|
||||
zoneToUpdate.setRightEdge(_tempZone.getRightEdge());
|
||||
zoneToUpdate.setTimeFrame(_tempZone.getTimeFrame());
|
||||
|
||||
return 1 ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
Zone* ZoneContainer:: searchZoneById(string _idOfZone)
|
||||
{
|
||||
Zone* result ;
|
||||
for(int i=0 ; i< numberOfActiveZones ; i++)
|
||||
{
|
||||
if(zonesSortedArray[i].getId() == _idOfZone)
|
||||
{
|
||||
result = zonesSortedArray[i] ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return result ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void ZoneContainer:: findOrUpdatePivotEdgesOnConfirm(double _ask,double _bid)
|
||||
{
|
||||
|
||||
bool foundSupport = false ;
|
||||
bool foundResistance = false ;
|
||||
|
||||
|
||||
for(int i=0 ; i<numberOfActiveZones ; i++) // FIND LOWER PIVOT EDGE
|
||||
{
|
||||
|
||||
if(zonesSortedArray[i].getState() != "STATE_WAITING")
|
||||
{
|
||||
if((zonesSortedArray[i].getHigherEdge() < _ask) && (zonesSortedArray[i].getType() == "TYPE_SUPPORT"))
|
||||
{
|
||||
pivotEdges[0] = i;
|
||||
foundSupport = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int i= numberOfActiveZones-1 ; i >=0 ; i--) // FIND HIGHER PIVOT EDGE
|
||||
{
|
||||
if(zonesSortedArray[i].getState()!= "STATE_WAITING")
|
||||
{
|
||||
if((zonesSortedArray[i].getLowerEdge() > _bid) && (zonesSortedArray[i].getType() == "TYPE_RESISTANCE"))
|
||||
{
|
||||
pivotEdges[1] = i;
|
||||
foundResistance = true ;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(foundSupport == false)
|
||||
{
|
||||
pivotEdges[0] = -1;
|
||||
}
|
||||
if(foundResistance == false)
|
||||
{
|
||||
pivotEdges[1] = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void ZoneContainer:: findOrUpdatePivotEdgesOnDelete()
|
||||
{
|
||||
bool foundSupport = false ;
|
||||
bool foundResistance = false ;
|
||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK) ;
|
||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
|
||||
for(int i=0 ; i<numberOfActiveZones ; i++) // FIND LOWER PIVOT EDGE
|
||||
{
|
||||
|
||||
if(zonesSortedArray[i].getState() != "STATE_WAITING")
|
||||
{
|
||||
if(zonesSortedArray[i].getHigherEdge() < ask)
|
||||
{
|
||||
pivotEdges[0] = i;
|
||||
foundSupport = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int i= numberOfActiveZones-1 ; i >=0 ; i--) // FIND HIGHER PIVOT EDGE
|
||||
{
|
||||
if(zonesSortedArray[i].getState()!= "STATE_WAITING")
|
||||
{
|
||||
if(zonesSortedArray[i].getLowerEdge() > bid)
|
||||
{
|
||||
pivotEdges[1] = i;
|
||||
foundResistance = true ;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(foundSupport == false)
|
||||
{
|
||||
pivotEdges[0] = -1;
|
||||
}
|
||||
if(foundResistance == false)
|
||||
{
|
||||
pivotEdges[1] = -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void ZoneContainer:: printPivotEdges()
|
||||
{
|
||||
|
||||
Print("Lower Edge Index: " + pivotEdges[0]);
|
||||
Print("Higher Edge Index: " + pivotEdges[1]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
Zone* ZoneContainer:: getLowerPivotIndexZone()
|
||||
{
|
||||
|
||||
if(pivotEdges[0] != -1)
|
||||
{
|
||||
return getZoneByIndex(pivotEdges[0]);
|
||||
}
|
||||
|
||||
return NULL ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
Zone* ZoneContainer:: getHigherPivotIndexZone()
|
||||
{
|
||||
|
||||
if(pivotEdges[1] != -1)
|
||||
{
|
||||
return getZoneByIndex(pivotEdges[1]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void ZoneContainer:: addResistanceZoneTiger(Zone* _newZone)
|
||||
{
|
||||
|
||||
|
||||
if((numberOfActiveZones != 0 ) && (_newZone.getLowerEdge() >= zonesSortedArray[0].getHigherEdge())) // this is the case, where the new zone shouldnt be placed at the beggining (gap case for instance)
|
||||
{
|
||||
|
||||
|
||||
int indexOfNewZone = searchForTheRightPlace(_newZone);
|
||||
if(indexOfNewZone != -1) // means found a place for the new zone
|
||||
{
|
||||
forwardShiftZonesSortedArrayFromIndex(indexOfNewZone);
|
||||
zonesSortedArray[indexOfNewZone] = _newZone ;
|
||||
numberOfActiveZones++;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Couldnt find an index to place the new zone !");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
forwardShiftZonesSortedArrayFromIndex(0);
|
||||
zonesSortedArray[0] = _newZone ;
|
||||
|
||||
if(_newZone.getType() == "TYPE_RESISTANCE_BREAKOUT")
|
||||
{
|
||||
numberOfActiveZones++;
|
||||
}
|
||||
else
|
||||
if(_newZone.getType() == "TYPE_RESISTANCE_NORMAL")
|
||||
{
|
||||
|
||||
numberOfActiveZones++ ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ZoneContainer:: addHistoryResistanceZoneOnTop(Zone* _newZone){
|
||||
zonesSortedArray[numberOfActiveZones] = _newZone ;
|
||||
numberOfActiveZones++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void ZoneContainer:: addSupportZoneTiger(Zone* _newZone)
|
||||
{
|
||||
|
||||
|
||||
/* if((numberOfActiveZones != 0 ) && (_newZone.getHigherEdge() <= zonesSortedArray[numberOfActiveZones-1].getLowerEdge())) // this is the case, where the new zone shouldnt be placed at the beggining (gap case for instance)
|
||||
{
|
||||
|
||||
|
||||
int indexOfNewZone = searchForTheRightPlace(_newZone);
|
||||
if(indexOfNewZone != -1) // means found a place for the new zone
|
||||
{
|
||||
forwardShiftZonesSortedArrayFromIndex(indexOfNewZone);
|
||||
zonesSortedArray[indexOfNewZone] = _newZone ;
|
||||
numberOfActiveZones++;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Couldnt find an index to place the new zone !");
|
||||
}
|
||||
|
||||
|
||||
} */
|
||||
|
||||
|
||||
|
||||
|
||||
zonesSortedArray[numberOfActiveZones] = _newZone ;
|
||||
|
||||
if(_newZone.getType() == "TYPE_SUPPORT_BREAKOUT")
|
||||
{
|
||||
numberOfActiveZones++;
|
||||
}
|
||||
else
|
||||
if(_newZone.getType() == "TYPE_SUPPORT_NORMAL")
|
||||
{
|
||||
|
||||
numberOfActiveZones++ ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
void ZoneContainer:: addHistorySupportZoneAtBottom(Zone* _newZone){
|
||||
|
||||
|
||||
forwardShiftZonesSortedArrayFromIndex(0);
|
||||
zonesSortedArray[0] = _newZone ;
|
||||
numberOfActiveZones++;
|
||||
}
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -0,0 +1,98 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| candleStringDetector.mq5 |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
#include "Algo_Skeleton_Functions.mqh"
|
||||
|
||||
int last_Color_candle = -1 ;
|
||||
int daily_streak_counter = 0 ;
|
||||
|
||||
string timeInStr = "--" ;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
//---
|
||||
|
||||
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//---
|
||||
|
||||
if(newCandleDetectorDaily.isNewCandle())
|
||||
{
|
||||
//objectsManager.drawVerticalLine(clrAliceBlue, TimeCurrent());
|
||||
if(candleClosedBullish(PERIOD_D1,1) && last_Color_candle != 1) // this is the first daily bullish candle
|
||||
{
|
||||
|
||||
// save the timeInStr and the daily streak counter in a row in excel
|
||||
string fileName = "daily_candle_streak.csv" ; // if you want to find the csv file, go to file -> open data folder -> mql5 -> files . all from the visual mode
|
||||
int fileHandle = FileOpen(fileName,FILE_READ|FILE_WRITE/* |FILE_CSV|FILE_ANSI*/);
|
||||
FileSeek(fileHandle,0,SEEK_END);
|
||||
FileWrite(fileHandle,timeInStr,daily_streak_counter);
|
||||
|
||||
FileClose(fileHandle);
|
||||
|
||||
datetime time = TimeCurrent(); // save the date of this day
|
||||
timeInStr = TimeToString(time,TIME_DATE);
|
||||
last_Color_candle = 1 ; // convert the flag to bullish
|
||||
daily_streak_counter = 0 ; // reset the counter
|
||||
|
||||
}
|
||||
else if(candleClosedBullish(PERIOD_D1,1) && last_Color_candle == 1)
|
||||
{
|
||||
|
||||
daily_streak_counter++ ;
|
||||
}
|
||||
|
||||
|
||||
if(candleClosedBearish(PERIOD_D1,1) && last_Color_candle != 0) // this is the first daily bearish candle
|
||||
{
|
||||
|
||||
// save the timeInStr and the daily streak counter in a row in excel
|
||||
string fileName = "daily_candle_streak.csv" ; // if you want to find the csv file, go to file -> open data folder -> mql5 -> files . all from the visual mode
|
||||
int fileHandle = FileOpen(fileName,FILE_READ|FILE_WRITE/* |FILE_CSV|FILE_ANSI*/);
|
||||
FileSeek(fileHandle,0,SEEK_END);
|
||||
FileWrite(fileHandle,timeInStr,daily_streak_counter);
|
||||
|
||||
FileClose(fileHandle);
|
||||
|
||||
datetime time = TimeCurrent();
|
||||
timeInStr = TimeToString(time,TIME_DATE);
|
||||
last_Color_candle = 0 ;
|
||||
daily_streak_counter = 0;
|
||||
}
|
||||
|
||||
else if(candleClosedBearish(PERIOD_D1,1) && last_Color_candle == 0){
|
||||
daily_streak_counter++ ;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,765 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| library_functions.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
|
||||
|
||||
|
||||
#include <Trade/Trade.mqh>
|
||||
|
||||
|
||||
|
||||
int findMondayFromLastPeriodWeeks(int _period);
|
||||
|
||||
// FRACTALS RELATED FUNCTIONS
|
||||
bool isLowFractalByIndex(int index, int leftPeriod, int rightPeriod, ENUM_TIMEFRAMES timeFrame); // checks if the given index candle is, a low fractal of the left, right periods
|
||||
bool isHighFractalByIndex(int index, int leftPeriod, int rightPeriod, ENUM_TIMEFRAMES timeFrame); // checks if the given index candle is, a high fractal of the left, right periods
|
||||
|
||||
// TIME FRAME RELATED FUNCTIONS
|
||||
string getChartTimeFrameInString() ; // gets the chart time frame in string format
|
||||
string timeFrameToString(ENUM_TIMEFRAMES _timeFrame);
|
||||
|
||||
// SESSIONS RELATED FUNCTIONS
|
||||
bool sessionIsNy(); // checks if the session is ny
|
||||
bool sessionIsLondon(); // checks if the session is london
|
||||
bool sessionIsTokyo();
|
||||
|
||||
|
||||
|
||||
// TRADE RELATED FUNCTIONS
|
||||
bool closePartialFromAllPositions(double partialAmount) ; // closes partial of all open positions the partial is partialAmount (parameter)
|
||||
bool closePartialFromSpecificPosition(ulong posTicket, double partialToClose) ; // closes a partial from the given position ticket
|
||||
bool stopLossIsValidBuys(double stopLoss, double _maxPipsRiskAmount);
|
||||
bool stopLossIsValidSells(double stopLoss,double _maxPipsRiskAmount);
|
||||
double positionProfitInPips(ulong posTicket); // returns the position profit in pips
|
||||
double positionStopLoss(ulong posTicket);
|
||||
void positionTrailStopLoss(ulong posTicket, double newStopLoss, double takeProfit);
|
||||
|
||||
|
||||
|
||||
// CANDLE ANATOMY RELATED FUNCTIONS
|
||||
bool buyBreakerCandleIsValid(ENUM_TIMEFRAMES _timeFrame, double _sizeOfBreakerCandleBody); // checks if the buy breaker candle is big enough
|
||||
bool sellBreakerCandleIsValid(ENUM_TIMEFRAMES _timeFrame, double _sizeOfBreakerCandleBody); // checks if the sell breaker candle is big enough
|
||||
bool bearishCandleIsWeak(ENUM_TIMEFRAMES _timeFrame, int index, double wickRatioRejection); // this function assumes that the previous candle is bearish
|
||||
bool bullishCandleIsWeak(ENUM_TIMEFRAMES _timeFrame, int index, double wickRatioRejection); // this function assumes that the previous candle is bullish
|
||||
double retestWickFormedOnTheFirstHalfOfCandle(ENUM_TIMEFRAMES _mainTimeFrame, ENUM_TIMEFRAMES _secondaryTimeFrame);
|
||||
bool candleClosedBullish(ENUM_TIMEFRAMES _timeFrame, int _index);
|
||||
bool candleClosedBearish(ENUM_TIMEFRAMES _timeFrame,int _index);
|
||||
bool candleClosedDoji(ENUM_TIMEFRAMES _timeFrame, int _index);
|
||||
bool candleBodyIsValid(ENUM_TIMEFRAMES _timeFrame, int _index); // this function is used for enhancing the detection of supports/resistances
|
||||
|
||||
|
||||
// SUPPORT AND RESISTANCE RELATED FUNCTIONS
|
||||
bool supportPatternFormed(ENUM_TIMEFRAMES _timeFrame, int _index=0); // _index = 0 is the default state which is a specific case of the general function with _index = i
|
||||
bool resistancePatternFormed(ENUM_TIMEFRAMES _timeFrame, int _index=0);// _index = 0 is the default state which is a specific case of the general function with _index = i
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* WARNING FOR THE NEXT FUNCTION*/
|
||||
/* IF A FRIDAY WAS NOT ON THE BROKER, THE FUNCTION WILL NOT COUNT THE WEEK. MAKE SURE BEFORE APPLYING IT TO SEE VISUALLY THAT IT WAS LAUNCHED RIGHT */
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int findMondayFromLastPeriodWeeks(int _period) { // _period = 1 means the previous week. _period = 2 means 2 weeks ago. and so on ...
|
||||
|
||||
int startCountFromIndex = 0 ;
|
||||
datetime localTime = TimeLocal();
|
||||
MqlDateTime dateTimeStructure ;
|
||||
TimeToStruct(localTime,dateTimeStructure);
|
||||
int dayOfTheWeek = dateTimeStructure.day_of_week;
|
||||
int hourOfTheDay = dateTimeStructure.hour;
|
||||
|
||||
if(dayOfTheWeek == 5) { // means if we called the function on friday , start counting from the candle of index 25, because our goal is to reach the pervious week friday, so we know we are in the previous week
|
||||
startCountFromIndex = 25 ;
|
||||
}
|
||||
if(dayOfTheWeek == 6 || dayOfTheWeek == 7) {
|
||||
Alert("Its saturday/sunday start next week !");
|
||||
}
|
||||
|
||||
MqlDateTime shiftedBarTimeStruct ;
|
||||
int weeksPassed = 0 ; // count of how many weeks we passed. it starts with 0 since we start at week 0. and will end in _period
|
||||
int lockCounter = 0;
|
||||
int i = startCountFromIndex ; // i represents the distance from the moment we started. by the end of the function it will point to the first monday of the desired week that we want
|
||||
while(weeksPassed < _period) {
|
||||
datetime shiftedBarTime=iTime(_Symbol,PERIOD_CURRENT,i); // take the date of the current candle
|
||||
TimeToStruct(shiftedBarTime,shiftedBarTimeStruct); // change the date to a struct
|
||||
|
||||
if(shiftedBarTimeStruct.day_of_week == 5 && lockCounter == 0) { // if we reached friday, add the weeksPassed by 1 and lock the block for the next friday
|
||||
weeksPassed++; // each time we reach a friday this means we are in a previous week. (we are counting the weeks starting from the current moment and going back in time)
|
||||
lockCounter++;
|
||||
|
||||
} else if(shiftedBarTimeStruct.day_of_week == 5 && lockCounter > 0) { // stay locked until we pass the current friday
|
||||
lockCounter++ ;
|
||||
} else if(shiftedBarTimeStruct.day_of_week == 4) { // if reached thursday , then release the lock
|
||||
lockCounter = 0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
Print("weeks passed value is: "+ weeksPassed);
|
||||
return i-2 ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ************************ FRACTALS FUNCTIONS ************************
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool isLowFractalByIndex(int index, int leftPeriod, int rightPeriod, ENUM_TIMEFRAMES timeFrame) { // checks if the given index candle is, a low fractal of the left, right periods
|
||||
|
||||
for(int i = index+1 ; i < (index + leftPeriod + 1) ; i++) {
|
||||
if(!(iLow(Symbol(),timeFrame,index) <= iLow(Symbol(),timeFrame,i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(index > rightPeriod) { // this means we have enough candles to the right
|
||||
|
||||
for(int j = index-1 ; (j > index - rightPeriod - 1) ; j--) {
|
||||
if(!(iLow(Symbol(),timeFrame,index) <= iLow(Symbol(),timeFrame,j))) {
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool isHighFractalByIndex(int index, int leftPeriod, int rightPeriod, ENUM_TIMEFRAMES timeFrame) { // checks if the given index candle is, a high fractal of the left, right periods
|
||||
|
||||
for(int i = index+1 ; i < (index + leftPeriod + 1) ; i++) {
|
||||
if(!(iHigh(Symbol(),timeFrame,index) >= iHigh(Symbol(),timeFrame,i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(index > rightPeriod) { // this means we have enough candles to the right
|
||||
|
||||
for(int j = index-1 ; (j > index - rightPeriod - 1) ; j--) {
|
||||
if(!(iHigh(Symbol(),timeFrame,index) >= iHigh(Symbol(),timeFrame,j))) {
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ************************ TIME FRAMES FUNCTIONS ************************
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
string getChartTimeFrameInString() {
|
||||
|
||||
ENUM_TIMEFRAMES period = Period();
|
||||
|
||||
switch(period) {
|
||||
|
||||
case PERIOD_M1:
|
||||
return "PERIOD_M1" ;
|
||||
break;
|
||||
|
||||
case PERIOD_M2:
|
||||
return "PERIOD_M2" ;
|
||||
break;
|
||||
|
||||
case PERIOD_M3:
|
||||
return "PERIOD_M3" ;
|
||||
break;
|
||||
|
||||
case PERIOD_M4:
|
||||
return "PERIOD_M4" ;
|
||||
break;
|
||||
|
||||
case PERIOD_M5:
|
||||
return "PERIOD_M5" ;
|
||||
break;
|
||||
|
||||
case PERIOD_M6:
|
||||
return "PERIOD_M6" ;
|
||||
break;
|
||||
case PERIOD_M10:
|
||||
return "PERIOD_M10" ;
|
||||
break;
|
||||
|
||||
case PERIOD_M12:
|
||||
return "PERIOD_M12" ;
|
||||
break;
|
||||
|
||||
case PERIOD_M15:
|
||||
return "PERIOD_M15" ;
|
||||
break;
|
||||
|
||||
case PERIOD_M20:
|
||||
return "PERIOD_M20" ;
|
||||
break;
|
||||
|
||||
case PERIOD_M30:
|
||||
return "PERIOD_M30" ;
|
||||
break;
|
||||
case PERIOD_H1:
|
||||
return "PERIOD_H1" ;
|
||||
break;
|
||||
|
||||
case PERIOD_H2:
|
||||
return "PERIOD_H2" ;
|
||||
break;
|
||||
|
||||
case PERIOD_H3:
|
||||
return "PERIOD_H3" ;
|
||||
break;
|
||||
|
||||
case PERIOD_H4:
|
||||
return "PERIOD_H4" ;
|
||||
break;
|
||||
|
||||
case PERIOD_H6:
|
||||
return "PERIOD_H6" ;
|
||||
break;
|
||||
|
||||
case PERIOD_H8:
|
||||
return "PERIOD_H8" ;
|
||||
break;
|
||||
case PERIOD_H12:
|
||||
return "PERIOD_H12" ;
|
||||
break;
|
||||
|
||||
case PERIOD_D1:
|
||||
return "PERIOD_D1" ;
|
||||
break;
|
||||
case PERIOD_W1:
|
||||
return "PERIOD_W1" ;
|
||||
break;
|
||||
|
||||
case PERIOD_MN1:
|
||||
return "PERIOD_MN1" ;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return "" ;
|
||||
}
|
||||
|
||||
|
||||
string timeFrameToString(ENUM_TIMEFRAMES _timeFrame){
|
||||
switch(_timeFrame) {
|
||||
|
||||
case PERIOD_M1:
|
||||
return "PERIOD_M1" ;
|
||||
break;
|
||||
|
||||
case PERIOD_M2:
|
||||
return "PERIOD_M2" ;
|
||||
break;
|
||||
|
||||
case PERIOD_M3:
|
||||
return "PERIOD_M3" ;
|
||||
break;
|
||||
|
||||
case PERIOD_M4:
|
||||
return "PERIOD_M4" ;
|
||||
break;
|
||||
|
||||
case PERIOD_M5:
|
||||
return "PERIOD_M5" ;
|
||||
break;
|
||||
|
||||
case PERIOD_M6:
|
||||
return "PERIOD_M6" ;
|
||||
break;
|
||||
case PERIOD_M10:
|
||||
return "PERIOD_M10" ;
|
||||
break;
|
||||
|
||||
case PERIOD_M12:
|
||||
return "PERIOD_M12" ;
|
||||
break;
|
||||
|
||||
case PERIOD_M15:
|
||||
return "PERIOD_M15" ;
|
||||
break;
|
||||
|
||||
case PERIOD_M20:
|
||||
return "PERIOD_M20" ;
|
||||
break;
|
||||
|
||||
case PERIOD_M30:
|
||||
return "PERIOD_M30" ;
|
||||
break;
|
||||
case PERIOD_H1:
|
||||
return "PERIOD_H1" ;
|
||||
break;
|
||||
|
||||
case PERIOD_H2:
|
||||
return "PERIOD_H2" ;
|
||||
break;
|
||||
|
||||
case PERIOD_H3:
|
||||
return "PERIOD_H3" ;
|
||||
break;
|
||||
|
||||
case PERIOD_H4:
|
||||
return "PERIOD_H4" ;
|
||||
break;
|
||||
|
||||
case PERIOD_H6:
|
||||
return "PERIOD_H6" ;
|
||||
break;
|
||||
|
||||
case PERIOD_H8:
|
||||
return "PERIOD_H8" ;
|
||||
break;
|
||||
case PERIOD_H12:
|
||||
return "PERIOD_H12" ;
|
||||
break;
|
||||
|
||||
case PERIOD_D1:
|
||||
return "PERIOD_D1" ;
|
||||
break;
|
||||
case PERIOD_W1:
|
||||
return "PERIOD_W1" ;
|
||||
break;
|
||||
|
||||
case PERIOD_MN1:
|
||||
return "PERIOD_MN1" ;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return "" ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ************************ SESSIONS FUNCTIONS ************************
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool sessionIsNy() {
|
||||
MqlDateTime mqldt ;
|
||||
datetime currTime = TimeCurrent(mqldt);
|
||||
|
||||
if(mqldt.hour >= 12 && mqldt.hour <= 20) {
|
||||
return true ;
|
||||
}
|
||||
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool sessionIsLondon() {
|
||||
MqlDateTime mqldt ;
|
||||
datetime currTime = TimeCurrent(mqldt);
|
||||
|
||||
if(mqldt.hour >= 8 && mqldt.hour <= 12) {
|
||||
return true ;
|
||||
}
|
||||
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool sessionIsTokyo(){
|
||||
MqlDateTime mqldt ;
|
||||
datetime currTime = TimeCurrent(mqldt);
|
||||
|
||||
if(mqldt.hour >= 4 && mqldt.hour <= 8) {
|
||||
return true ;
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
// ************************ TRADE FUNCTIONS ************************
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool closePartialFromAllPositions(double partialAmount) {
|
||||
CTrade trade ;
|
||||
for(uint i=0 ; i< PositionsTotal() ; i++) {
|
||||
|
||||
ulong positionTicket = PositionGetTicket(i);
|
||||
if(PositionSelectByTicket(positionTicket)) {
|
||||
|
||||
double positionVolume = PositionGetDouble(POSITION_VOLUME);
|
||||
double lotsToClose = positionVolume * partialAmount ;
|
||||
if(trade.PositionClosePartial(positionTicket,NormalizeDouble(lotsToClose,2))) {
|
||||
Print("Closed partials succesffully");
|
||||
return true ;
|
||||
} else {
|
||||
Print("Failed to close partials, Error: " + GetLastError());
|
||||
return false ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool closePartialFromSpecificPosition(ulong posTicket, double partialToClose) {
|
||||
|
||||
CTrade trade ;
|
||||
double positionVolume = PositionGetDouble(POSITION_VOLUME);
|
||||
double lotsToClose = positionVolume * partialToClose ;
|
||||
if(trade.PositionClosePartial(posTicket,NormalizeDouble(lotsToClose,2))) {
|
||||
|
||||
return true ;
|
||||
|
||||
} else {
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool stopLossIsValidBuys(double stopLoss, double _maxPipsRiskAmount) {
|
||||
|
||||
if(SymbolInfoDouble(_Symbol, SYMBOL_ASK) - stopLoss < _maxPipsRiskAmount) {
|
||||
return true ;
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double positionProfitInPips(ulong posTicket) {
|
||||
|
||||
double currentProfitInPips = -1 ;
|
||||
if(PositionSelectByTicket(posTicket)) {
|
||||
|
||||
double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT) ;
|
||||
double positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
|
||||
|
||||
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
|
||||
currentProfitInPips = currentPrice - positionOpenPrice ;
|
||||
}
|
||||
|
||||
else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {
|
||||
|
||||
currentProfitInPips = positionOpenPrice - currentPrice ;
|
||||
}
|
||||
} else {
|
||||
|
||||
Comment("Error from positionProfitInPips() function: Failed to select position, Error " + GetLastError());
|
||||
}
|
||||
|
||||
|
||||
|
||||
return currentProfitInPips ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
double positionStopLoss(ulong posTicket) {
|
||||
|
||||
double posStopLoss = -1 ;
|
||||
if(PositionSelectByTicket(posTicket)) {
|
||||
posStopLoss = PositionGetDouble(POSITION_SL) ;
|
||||
|
||||
} else {
|
||||
Comment("Error from positionStopLoss() function: Failed to select position, Error " + GetLastError());
|
||||
}
|
||||
|
||||
return posStopLoss;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool stopLossIsValidSells(double stopLoss,double _maxPipsRiskAmount) {
|
||||
if(stopLoss - SymbolInfoDouble(_Symbol, SYMBOL_BID) < _maxPipsRiskAmount) {
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void positionTrailStopLoss(ulong posTicket, double newStopLoss, double takeProfit) {
|
||||
|
||||
CTrade trade ;
|
||||
trade.PositionModify(posTicket,newStopLoss,takeProfit);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ************************ CANDLE ANATOMY FUNCTIONS ************************
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool buyBreakerCandleIsValid(ENUM_TIMEFRAMES _timeFrame, double _sizeOfBreakerCandleBody) {
|
||||
|
||||
if((iClose(_Symbol,_timeFrame,1) - iOpen(_Symbol,_timeFrame,1)) >= _sizeOfBreakerCandleBody) {
|
||||
return true ;
|
||||
} else {
|
||||
datetime currTime = TimeCurrent();
|
||||
string timeInStr = TimeToString(currTime,TIME_MINUTES);
|
||||
Comment(timeInStr + " Bullish Breaker candle body is too small to take a trade !");
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool sellBreakerCandleIsValid(ENUM_TIMEFRAMES _timeFrame, double _sizeOfBreakerCandleBody) {
|
||||
if((iOpen(_Symbol,_timeFrame,1) - iClose(_Symbol,_timeFrame,1)) >= _sizeOfBreakerCandleBody) {
|
||||
return true ;
|
||||
} else {
|
||||
datetime currTime = TimeCurrent();
|
||||
string timeInStr = TimeToString(currTime,TIME_MINUTES);
|
||||
Comment(timeInStr + " Bearish Breaker candle body is too small to take a trade !");
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool bearishCandleIsWeak(ENUM_TIMEFRAMES _timeFrame, int index, double wickRatioRejection) { // this function assumes that the previous candle is bearish
|
||||
|
||||
double upperWickLength = iHigh(_Symbol,_timeFrame,index) - iOpen(_Symbol,_timeFrame,index) ;
|
||||
double totalCandleLength = iHigh(_Symbol,_timeFrame,index) - iClose(_Symbol,_timeFrame,index);
|
||||
if((upperWickLength / totalCandleLength) >= wickRatioRejection) { // this means the candle is weak
|
||||
Comment("Bearish Candle Is Weak");
|
||||
return true ;
|
||||
} else {
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool bullishCandleIsWeak(ENUM_TIMEFRAMES _timeFrame, int index, double wickRatioRejection) { // this function assumes that the previous candle is bullish
|
||||
double lowerWickLength = iOpen(_Symbol,_timeFrame,index) - iLow(_Symbol,_timeFrame,index) ;
|
||||
double totalCandleLength = iClose(_Symbol,_timeFrame,index) - iLow(_Symbol,_timeFrame,index) ;
|
||||
|
||||
if((lowerWickLength/totalCandleLength) >= wickRatioRejection) { // this means the candle is weak
|
||||
Comment("Bullish Candle is weak");
|
||||
return true ;
|
||||
} else {
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool candleClosedBullish(ENUM_TIMEFRAMES _timeFrame, int _index) {
|
||||
double candleClose = iClose(_Symbol,_timeFrame,_index);
|
||||
double candleOpen = iOpen(_Symbol,_timeFrame,_index);
|
||||
|
||||
|
||||
if(candleClose >candleOpen) { // the candle closed bullish
|
||||
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool candleClosedBearish(ENUM_TIMEFRAMES _timeFrame,int _index) {
|
||||
|
||||
|
||||
double candleClose = iClose(_Symbol,_timeFrame,_index);
|
||||
double candleOpen = iOpen(_Symbol,_timeFrame,_index);
|
||||
|
||||
|
||||
if(candleClose < candleOpen) { // the candle closed bullish
|
||||
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool candleClosedDoji(ENUM_TIMEFRAMES _timeFrame, int _index) {
|
||||
double candleClose = iClose(_Symbol,_timeFrame,_index);
|
||||
double candleOpen = iOpen(_Symbol,_timeFrame,_index);
|
||||
|
||||
if(candleClose == candleOpen) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool candleBodyIsValid(ENUM_TIMEFRAMES _timeFrame, int _index) {
|
||||
double candleClose = iClose(_Symbol,_timeFrame,_index);
|
||||
double candleOpen = iOpen(_Symbol,_timeFrame,_index);
|
||||
double candleHigh = iHigh(_Symbol,_timeFrame,_index);
|
||||
double candleLow = iLow(_Symbol,_timeFrame,_index);
|
||||
double topWickSize ;
|
||||
double bottomWickSize ;
|
||||
double candleBodySize ;
|
||||
|
||||
if(candleClosedBearish(_timeFrame,_index)) {
|
||||
topWickSize = candleHigh - candleOpen ;
|
||||
bottomWickSize = candleClose - candleLow ;
|
||||
candleBodySize = candleOpen - candleClose ;
|
||||
|
||||
} else if(candleClosedBullish(_timeFrame,_index)) {
|
||||
topWickSize = candleHigh - candleClose ;
|
||||
bottomWickSize = candleOpen - candleLow ;
|
||||
candleBodySize = candleClose - candleOpen ;
|
||||
} else if(candleClosedDoji(_timeFrame,_index)) {
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
if((topWickSize >= (15*candleBodySize)) || (bottomWickSize >= (15* candleBodySize))) { // 8 is fixed number ,
|
||||
//which means that if i find a candle's wick that is 15 times bigger than the body then i dont want to consider it when detecting a support or resistance, this is for the cases that the candle looks almost like a doji but not an actual doji
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
/*double retestWickFormedOnTheFirstHalfOfCandle(ENUM_TIMEFRAMES _mainTimeFrame, ENUM_TIMEFRAMES _secondaryTimeFrame){
|
||||
|
||||
if(candleClosedBullish(_mainTimeFrame,1)){ // previous candle closed bullish, this means checking a wick on a bullish candle on the main timeframe
|
||||
if(candleClosedBearish(_secondaryTimeFrame)){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(candleClosedBearish(_mainTimeFrame)){ // previous candle closed bullish, this means checking a wick on a bearish candle on the main timeframe
|
||||
|
||||
}
|
||||
|
||||
} */
|
||||
|
||||
|
||||
// ************************ SUPPORT AND RESISTANCE RELATED FUNCTIONS ************************
|
||||
|
||||
|
||||
/*bool supportPatternFormed(ENUM_TIMEFRAMES _timeFrame){ // this is a spicific case of the next function, the _index parameter here is 0
|
||||
if((candleClosedBearish(_timeFrame,2) && candleClosedBullish(_timeFrame,1) && candleBodyIsValid(_timeFrame,1)&& candleBodyIsValid(_timeFrame,2))
|
||||
|| (candleClosedBearish(_timeFrame,3) && candleClosedDoji(_timeFrame,2) && candleClosedBullish(_timeFrame,1))
|
||||
|| candleClosedBearish(_timeFrame,3) && candleBodyIsValid(_timeFrame,3) && !candleBodyIsValid(_timeFrame,2) && candleClosedBullish(_timeFrame,1) && candleBodyIsValid(_timeFrame,1)) {
|
||||
return true ;
|
||||
|
||||
}
|
||||
return false ;
|
||||
}*/
|
||||
|
||||
|
||||
bool supportPatternFormed(ENUM_TIMEFRAMES _timeFrame, int _index = 0){ // this is the same previous function but with geniric index to detect the support on . its used for detecing old supports (that are not currently happeneing)
|
||||
|
||||
|
||||
if((candleClosedBearish(_timeFrame,_index+2) && candleClosedBullish(_timeFrame,_index+1) && candleBodyIsValid(_timeFrame,_index+1)&& candleBodyIsValid(_timeFrame,_index+2))
|
||||
|| (candleClosedBearish(_timeFrame,_index+3) && candleClosedDoji(_timeFrame,_index+2) && candleClosedBullish(_timeFrame,_index+1))
|
||||
|| candleClosedBearish(_timeFrame,_index+3) && candleBodyIsValid(_timeFrame,_index+3) && !candleBodyIsValid(_timeFrame,_index + 2) && candleClosedBullish(_timeFrame,_index+1)
|
||||
&& candleBodyIsValid(_timeFrame,_index+1) ){
|
||||
return true ;
|
||||
|
||||
}
|
||||
return false ;
|
||||
|
||||
}
|
||||
bool resistancePatternFormed(ENUM_TIMEFRAMES _timeFrame, int _index = 0){ // this is a spicific case of the next function
|
||||
|
||||
if((candleClosedBullish(_timeFrame,_index+2) && candleClosedBearish(_timeFrame,_index+1) && candleBodyIsValid(_timeFrame,_index+2) && candleBodyIsValid(_timeFrame,_index+1))
|
||||
|| (candleClosedBullish(_timeFrame,3) && candleClosedDoji(_timeFrame,2) && candleClosedBearish(_timeFrame,1) )){
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -0,0 +1,404 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Breakout_Fractals.mq5 |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//#include "Algo_Skeleton_Functions.mqh"
|
||||
#include "Phoenix_Functions.mqh"
|
||||
|
||||
bool trailWhenMarketOpensDaily = false ;
|
||||
int OnInit()
|
||||
{
|
||||
//---
|
||||
|
||||
//---
|
||||
for(int i=0; i<NUM_MAX_ALLOWED_TRADES ; i++)
|
||||
{
|
||||
BuyActiveTradesArray[i] = NULL ;
|
||||
SellActiveTradesArray[i] = NULL ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
objectsManager.addTextTiger();
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//---
|
||||
Print("Buys Count: " + buysCount);
|
||||
Print("Sells Count: " + sellsCount);
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//---
|
||||
cleanBuyTradesArr();
|
||||
cleanSellTradesArr();
|
||||
|
||||
|
||||
|
||||
if(newCandleDetectorM5.isNewCandle())
|
||||
{
|
||||
if(APPLY_TRAIL && TRAIL_TIME_FRAME == PERIOD_M5){
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_M5);
|
||||
}
|
||||
if(TIME_FRAME_TO_TRADE == PERIOD_M5)
|
||||
{
|
||||
datetime currTime = TimeCurrent();
|
||||
Comment(TimeToString(currTime,TIME_MINUTES) + ": Sell Below: " + currentSupportLowerEdge + " Buy Above: "+ currentResistanceHighEdge);
|
||||
|
||||
string timeFrameStr = timeFrameToString(TIME_FRAME_TO_TRADE);
|
||||
|
||||
findAndDrawFractalsAndZones(TIME_FRAME_TO_TRADE,timeFrameStr);
|
||||
|
||||
if(candleClosedBelowSupportZone(TIME_FRAME_TO_TRADE)) // SELL CASE
|
||||
{
|
||||
handleSells();
|
||||
}
|
||||
|
||||
|
||||
if(candleClosedAboveResistanceZone(TIME_FRAME_TO_TRADE)) // BUY CASE
|
||||
{
|
||||
handleBuys();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(newCandleDetectorM15.isNewCandle())
|
||||
{
|
||||
if(APPLY_TRAIL && TRAIL_TIME_FRAME == PERIOD_M15){
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_M15);
|
||||
}
|
||||
if(TIME_FRAME_TO_TRADE == PERIOD_M15)
|
||||
{
|
||||
datetime currTime = TimeCurrent();
|
||||
Comment(TimeToString(currTime,TIME_MINUTES) + ": Sell Below: " + currentSupportLowerEdge + " Buy Above: "+ currentResistanceHighEdge);
|
||||
|
||||
string timeFrameStr = timeFrameToString(TIME_FRAME_TO_TRADE);
|
||||
|
||||
findAndDrawFractalsAndZones(TIME_FRAME_TO_TRADE,timeFrameStr);
|
||||
|
||||
if(candleClosedBelowSupportZone(TIME_FRAME_TO_TRADE)) // SELL CASE
|
||||
{
|
||||
handleSells();
|
||||
}
|
||||
|
||||
|
||||
if(candleClosedAboveResistanceZone(TIME_FRAME_TO_TRADE)) // BUY CASE
|
||||
{
|
||||
handleBuys();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(newCandleDetectorM30.isNewCandle())
|
||||
{
|
||||
|
||||
if(APPLY_TRAIL && TRAIL_TIME_FRAME == PERIOD_M30){
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_M30);
|
||||
}
|
||||
if(TIME_FRAME_TO_TRADE == PERIOD_M30)
|
||||
{
|
||||
|
||||
datetime currTime = TimeCurrent();
|
||||
Comment(TimeToString(currTime,TIME_MINUTES) + ": Sell Below: " + currentSupportLowerEdge + " Buy Above: "+ currentResistanceHighEdge);
|
||||
|
||||
string timeFrameStr = timeFrameToString(TIME_FRAME_TO_TRADE);
|
||||
|
||||
findAndDrawFractalsAndZones(TIME_FRAME_TO_TRADE,timeFrameStr);
|
||||
|
||||
if(candleClosedBelowSupportZone(TIME_FRAME_TO_TRADE)) // SELL CASE
|
||||
{
|
||||
handleSells();
|
||||
}
|
||||
|
||||
|
||||
if(candleClosedAboveResistanceZone(TIME_FRAME_TO_TRADE)) // BUY CASE
|
||||
{
|
||||
handleBuys();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(newCandleDetectorH1.isNewCandle())
|
||||
{
|
||||
if(APPLY_TRAIL && TRAIL_TIME_FRAME == PERIOD_D1 && trailWhenMarketOpensDaily){
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_D1);
|
||||
trailWhenMarketOpensDaily = false ;
|
||||
}
|
||||
if(APPLY_TRAIL && (TRAIL_TIME_FRAME == PERIOD_H1)){
|
||||
Print("Entered the trail !");
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_H1);
|
||||
}
|
||||
if(TIME_FRAME_TO_TRADE == PERIOD_H1)
|
||||
{
|
||||
datetime currTime = TimeCurrent();
|
||||
Comment(TimeToString(currTime,TIME_MINUTES) + ": Sell Below: " + currentSupportLowerEdge + " Buy Above: "+ currentResistanceHighEdge);
|
||||
|
||||
string timeFrameStr = timeFrameToString(TIME_FRAME_TO_TRADE);
|
||||
|
||||
findAndDrawFractalsAndZones(TIME_FRAME_TO_TRADE,timeFrameStr);
|
||||
|
||||
if(candleClosedBelowSupportZone(TIME_FRAME_TO_TRADE)) // SELL CASE
|
||||
{
|
||||
handleSells();
|
||||
}
|
||||
|
||||
|
||||
if(candleClosedAboveResistanceZone(TIME_FRAME_TO_TRADE)) // BUY CASE
|
||||
{
|
||||
handleBuys();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(newCandleDetectorH4.isNewCandle())
|
||||
{
|
||||
if(APPLY_TRAIL && TRAIL_TIME_FRAME == PERIOD_H4){
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_H4);
|
||||
}
|
||||
if(TIME_FRAME_TO_TRADE == PERIOD_H4)
|
||||
{
|
||||
|
||||
datetime currTime = TimeCurrent();
|
||||
Comment(TimeToString(currTime,TIME_MINUTES) + ": Sell Below: " + currentSupportLowerEdge + " Buy Above: "+ currentResistanceHighEdge);
|
||||
|
||||
string timeFrameStr = timeFrameToString(TIME_FRAME_TO_TRADE);
|
||||
|
||||
findAndDrawFractalsAndZones(TIME_FRAME_TO_TRADE,timeFrameStr);
|
||||
|
||||
if(candleClosedBelowSupportZone(TIME_FRAME_TO_TRADE)) // SELL CASE
|
||||
{
|
||||
handleSells();
|
||||
}
|
||||
|
||||
|
||||
if(candleClosedAboveResistanceZone(TIME_FRAME_TO_TRADE)) // BUY CASE
|
||||
{
|
||||
handleBuys();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(newCandleDetectorDaily.isNewCandle())
|
||||
{
|
||||
if(APPLY_TRAIL && TRAIL_TIME_FRAME == PERIOD_D1){
|
||||
trailWhenMarketOpensDaily = true ;
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_D1);
|
||||
}
|
||||
objectsManager.drawVerticalLine(clrAqua, TimeCurrent());
|
||||
}
|
||||
|
||||
if(newCandleDetectorWeekly.isNewCandle())
|
||||
{
|
||||
if(APPLY_TRAIL && TRAIL_TIME_FRAME == PERIOD_W1){
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_W1);
|
||||
}
|
||||
objectsManager.drawVerticalLine(clrRed, TimeCurrent());;
|
||||
}
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void handleSells()
|
||||
{
|
||||
|
||||
datetime currTime = TimeCurrent();
|
||||
|
||||
Comment(TimeToString(currTime,TIME_MINUTES) + ": im taking a sell !");
|
||||
|
||||
if(((indexToNewTrade = findAvailableSpotInSellManagerArr()) != -1))
|
||||
{
|
||||
|
||||
double stopLossPrice = calculateStopLossBasedOnFractalsSells(stopLossFractalsPeriod,stopLossTimeFrame) ;
|
||||
stopLossPrice = stopLossPrice + stopLossAboveWickByActual ;
|
||||
|
||||
if(stopLossIsValidSells(stopLossPrice,maxPipsRiskAmountActual))
|
||||
{
|
||||
if(rrFactor != -1 && lotSize == -1) // tp based rr metehod
|
||||
{
|
||||
if(SELLS_ALLOWED){
|
||||
double stopLossInPips = stopLossPrice - SymbolInfoDouble(_Symbol,SYMBOL_BID) ;
|
||||
double netTp = rrFactor * stopLossInPips ;
|
||||
double lotsToTrade = lsCalc.calculateLotSize(riskDollars,stopLossPrice);
|
||||
activeTradeId = sellEntryManager.takeSellTradeTiger(lotsToTrade,stopLossPrice,SymbolInfoDouble(_Symbol,SYMBOL_BID)- netTp) ;
|
||||
|
||||
SellTradeManagerTiger* tempTigerManagerSell= new SellTradeManagerTiger(activeTradeId); // create an object of type sellTradeManagerTiger
|
||||
|
||||
tempTigerManagerSell.setBrokenSupportHigherEdge(currentSupportHighEdge);
|
||||
tempTigerManagerSell.setBrokenSupportLowerEdge(currentSupportLowerEdge);
|
||||
SellActiveTradesArray[indexToNewTrade] = tempTigerManagerSell ;// put the new object in the array
|
||||
|
||||
sellsCount++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
if(rrFactor == -1 && lotSize == -1) // tp based net take profit method
|
||||
{
|
||||
if(SELLS_ALLOWED){
|
||||
double lotsToTrade = lsCalc.calculateLotSize(riskDollars,stopLossPrice);
|
||||
activeTradeId = sellEntryManager.takeSellTradeTiger(lotsToTrade,stopLossPrice,SymbolInfoDouble(_Symbol,SYMBOL_BID)- netTakeProfit) ;
|
||||
|
||||
SellTradeManagerTiger* tempTigerManagerSell= new SellTradeManagerTiger(activeTradeId); // create an object of type sellTradeManagerTiger
|
||||
|
||||
tempTigerManagerSell.setBrokenSupportHigherEdge(currentSupportHighEdge);
|
||||
tempTigerManagerSell.setBrokenSupportLowerEdge(currentSupportLowerEdge);
|
||||
SellActiveTradesArray[indexToNewTrade] = tempTigerManagerSell ;// put the new object in the array
|
||||
|
||||
sellsCount++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if(lotSize != -1){ // taking an entry based on fixed lot , and managing risk via trail
|
||||
if(SELLS_ALLOWED){
|
||||
activeTradeId = sellEntryManager.takeSellTradeTiger(lotSize,stopLossPrice) ;
|
||||
SellTradeManagerTiger* tempTigerManagerSell= new SellTradeManagerTiger(activeTradeId); // create an object of type sellTradeManagerTiger
|
||||
tempTigerManagerSell.setBrokenSupportHigherEdge(currentSupportHighEdge);
|
||||
tempTigerManagerSell.setBrokenSupportLowerEdge(currentSupportLowerEdge);
|
||||
SellActiveTradesArray[indexToNewTrade] = tempTigerManagerSell ;// put the new object in the array
|
||||
|
||||
sellsCount++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("stop loss is not valid sells!");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Comment("i cant take a trade because the arrray is full");
|
||||
}
|
||||
|
||||
currentSupportLowerEdge = -1;
|
||||
currentSupportHighEdge = -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void handleBuys()
|
||||
{
|
||||
|
||||
datetime currTime = TimeCurrent();
|
||||
Comment(TimeToString(currTime,TIME_MINUTES) + ": im taking a buy !");
|
||||
|
||||
|
||||
|
||||
if(((indexToNewTrade = findAvailableSpotInBuyManagerArr()) != -1))
|
||||
{
|
||||
|
||||
Print("indexToNewTrade:-------------------------------------------- " + indexToNewTrade);
|
||||
|
||||
double stopLossPrice = calculateStopLossBasedOnFractalsBuys(stopLossFractalsPeriod,stopLossTimeFrame);
|
||||
stopLossPrice = stopLossPrice - stopLossUnderWickByActual ;
|
||||
|
||||
if(stopLossIsValidBuys(stopLossPrice,maxPipsRiskAmountActual))
|
||||
{
|
||||
|
||||
if(rrFactor != -1 && lotSize == -1)
|
||||
{
|
||||
if(BUYS_ALLOWED){
|
||||
double stopLossInPips = SymbolInfoDouble(_Symbol,SYMBOL_ASK) - stopLossPrice ;
|
||||
double netTp = rrFactor * stopLossInPips ;
|
||||
double lotsToTrade = lsCalc.calculateLotSize(riskDollars,stopLossPrice);
|
||||
activeTradeId = buyEntryManager.takeBuyTradeTiger(lotsToTrade,stopLossPrice,SymbolInfoDouble(_Symbol,SYMBOL_ASK)+ netTp) ;
|
||||
|
||||
BuyTradeManagerTiger* tempTigerManagerBuy= new BuyTradeManagerTiger(activeTradeId); // create an object of type sellTradeManagerTiger
|
||||
tempTigerManagerBuy.setBrokenResistanceHigherEdge(currentResistanceHighEdge);
|
||||
tempTigerManagerBuy.setBrokenResistancetLowerEdge(currentResistanceLowEdge);
|
||||
BuyActiveTradesArray[indexToNewTrade] = tempTigerManagerBuy ;// put the new object in the array
|
||||
buysCount++;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
if(rrFactor == -1 && lotSize == -1)
|
||||
{
|
||||
if(BUYS_ALLOWED){
|
||||
double lotsToTrade = lsCalc.calculateLotSize(riskDollars,stopLossPrice);
|
||||
activeTradeId = buyEntryManager.takeBuyTradeTiger(lotsToTrade,stopLossPrice,SymbolInfoDouble(_Symbol,SYMBOL_ASK)+ netTakeProfit) ;
|
||||
|
||||
BuyTradeManagerTiger* tempTigerManagerBuy= new BuyTradeManagerTiger(activeTradeId); // create an object of type sellTradeManagerTiger
|
||||
tempTigerManagerBuy.setBrokenResistanceHigherEdge(currentResistanceHighEdge);
|
||||
tempTigerManagerBuy.setBrokenResistancetLowerEdge(currentResistanceLowEdge);
|
||||
BuyActiveTradesArray[indexToNewTrade] = tempTigerManagerBuy ;// put the new object in the array
|
||||
buysCount++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if(lotSize != -1){ // taking an entry based on fixed lot , and managing risk via trail
|
||||
|
||||
if(BUYS_ALLOWED){
|
||||
activeTradeId = buyEntryManager.takeBuyTradeTiger(lotSize,stopLossPrice) ;
|
||||
|
||||
BuyTradeManagerTiger* tempTigerManagerBuy= new BuyTradeManagerTiger(activeTradeId); // create an object of type sellTradeManagerTiger
|
||||
tempTigerManagerBuy.setBrokenResistanceHigherEdge(currentResistanceHighEdge);
|
||||
tempTigerManagerBuy.setBrokenResistancetLowerEdge(currentResistanceLowEdge);
|
||||
BuyActiveTradesArray[indexToNewTrade] = tempTigerManagerBuy ;// put the new object in the array
|
||||
buysCount++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("stop loss is not valid buys !");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Comment("i cant take a trade because the arrray is full");
|
||||
}
|
||||
|
||||
currentResistanceHighEdge = -1;
|
||||
currentResistanceLowEdge = -1;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,113 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BuyEntryManager.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include "BuyRejectionDetector.mqh"
|
||||
#include <Trade/Trade.mqh>
|
||||
|
||||
CTrade tradeLong ;
|
||||
class BuyEntryManager
|
||||
{
|
||||
private:
|
||||
|
||||
bool longTradeTaken ;
|
||||
bool waitingForRejectionCandle;
|
||||
bool waitingForRetracement ;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
BuyEntryManager();
|
||||
~BuyEntryManager();
|
||||
|
||||
BuyRejectionDetector* buyRejectionDetector ;
|
||||
|
||||
bool isWaitingForRejectionCandle(){return waitingForRejectionCandle ;}
|
||||
void setWaitingForRejectionCandle(bool _setting){waitingForRejectionCandle = _setting ;}
|
||||
|
||||
bool isWaitingForRetracement(){return waitingForRetracement;}
|
||||
void setWaitingForRetracement(bool _setting){waitingForRetracement = _setting ;}
|
||||
|
||||
bool buyTradeTaken();
|
||||
void setTradeTakenStatus(bool _status){longTradeTaken = _status ; Print("long trade taken flag has been set to true");}
|
||||
|
||||
|
||||
ulong takeBuyTrade(double _lots,double _stopLoss);
|
||||
ulong takeBuyTradeTiger(double _lots,double _stopLoss,double _takeProfit);
|
||||
ulong takeBuyTradeTiger(double _lots,double _stopLoss);
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyEntryManager::BuyEntryManager()
|
||||
{
|
||||
buyRejectionDetector = new BuyRejectionDetector();
|
||||
longTradeTaken = false ;
|
||||
waitingForRejectionCandle = false ;
|
||||
waitingForRetracement = false ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyEntryManager::~BuyEntryManager()
|
||||
{
|
||||
delete buyRejectionDetector ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
bool BuyEntryManager:: buyTradeTaken(){
|
||||
|
||||
|
||||
return longTradeTaken ;
|
||||
}
|
||||
|
||||
|
||||
ulong BuyEntryManager:: takeBuyTrade(double _lots, double _stopLoss){
|
||||
|
||||
tradeLong.Buy(NormalizeDouble(_lots,2),_Symbol,SymbolInfoDouble(_Symbol, SYMBOL_ASK),_stopLoss);
|
||||
|
||||
ulong tradeTicket = tradeLong.ResultOrder();
|
||||
|
||||
Print("Buy entry manager has taken a trade, ticket: " + tradeTicket);
|
||||
return tradeTicket;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
ulong BuyEntryManager:: takeBuyTradeTiger(double _lots,double _stopLoss, double _takeProft){ // first version, take the buy with fixed tp
|
||||
|
||||
double netTp = _takeProft - SymbolInfoDouble(_Symbol, SYMBOL_ASK) ;
|
||||
|
||||
tradeLong.Buy(NormalizeDouble(_lots,2),_Symbol,SymbolInfoDouble(_Symbol, SYMBOL_ASK),_stopLoss,SymbolInfoDouble(_Symbol, SYMBOL_ASK) + netTp);
|
||||
|
||||
ulong tradeTicket = tradeLong.ResultOrder();
|
||||
|
||||
Print("Buy entry manager has taken a trade, ticket: " + tradeTicket);
|
||||
return tradeTicket;
|
||||
|
||||
}
|
||||
|
||||
|
||||
ulong BuyEntryManager:: takeBuyTradeTiger(double _lots,double _stopLoss){ // second version, take the buy without a fixed tp
|
||||
|
||||
|
||||
tradeLong.Buy(NormalizeDouble(_lots,2),_Symbol,SymbolInfoDouble(_Symbol, SYMBOL_ASK),_stopLoss);
|
||||
|
||||
ulong tradeTicket = tradeLong.ResultOrder();
|
||||
|
||||
Print("Buy entry manager has taken a trade, ticket: " + tradeTicket);
|
||||
return tradeTicket;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BuyGandalf.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade/Trade.mqh>
|
||||
|
||||
CTrade tradeLong ;
|
||||
class BuyGandalf
|
||||
{
|
||||
private:
|
||||
|
||||
bool longTradeTaken ;
|
||||
ulong longTrades[10] ;
|
||||
|
||||
|
||||
public:
|
||||
BuyGandalf();
|
||||
~BuyGandalf();
|
||||
|
||||
|
||||
|
||||
bool buyTradeTaken();
|
||||
void setTradeTakenStatus(bool _status){longTradeTaken = _status ; Print("long trade taken flag has been set to true");}
|
||||
|
||||
|
||||
ulong takeBuyTrade(double _lots,double _stopLoss);
|
||||
ulong takeBuyTradeGandalf(double _lots,double _stopLoss);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyGandalf::BuyGandalf()
|
||||
{
|
||||
|
||||
longTradeTaken = false ;
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyGandalf::~BuyGandalf()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
bool BuyGandalf:: buyTradeTaken(){
|
||||
|
||||
|
||||
return longTradeTaken ;
|
||||
}
|
||||
|
||||
|
||||
ulong BuyGandalf:: takeBuyTrade(double _lots, double _stopLoss){
|
||||
|
||||
tradeLong.Buy(NormalizeDouble(_lots,2),_Symbol,SymbolInfoDouble(_Symbol, SYMBOL_ASK),_stopLoss);
|
||||
|
||||
ulong tradeTicket = tradeLong.ResultOrder();
|
||||
|
||||
Print("Buy entry manager has taken a trade, ticket: " + tradeTicket);
|
||||
return tradeTicket;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
ulong BuyGandalf:: takeBuyTradeGandalf(double _lots,double _stopLoss){
|
||||
|
||||
tradeLong.Buy(NormalizeDouble(_lots,2),_Symbol,SymbolInfoDouble(_Symbol, SYMBOL_ASK),_stopLoss);
|
||||
|
||||
ulong tradeTicket = tradeLong.ResultOrder();
|
||||
|
||||
Print("Buy entry manager has taken a trade, ticket: " + tradeTicket);
|
||||
return tradeTicket;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BuyRejectionDetector.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
class BuyRejectionDetector
|
||||
{
|
||||
private:
|
||||
|
||||
public:
|
||||
BuyRejectionDetector();
|
||||
~BuyRejectionDetector();
|
||||
|
||||
bool rejectionByOneCandleFormed(ENUM_TIMEFRAMES _timeFrame);
|
||||
bool rejectionByRangeFormed();
|
||||
bool rejectionByWicksFormed();
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyRejectionDetector::BuyRejectionDetector()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyRejectionDetector::~BuyRejectionDetector()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
bool BuyRejectionDetector:: rejectionByOneCandleFormed(ENUM_TIMEFRAMES _timeFrame){
|
||||
|
||||
double rejectionCandleClose = iClose(_Symbol,_timeFrame,1);
|
||||
double rejectionCandleOpen = iOpen(_Symbol,_timeFrame,1);
|
||||
double rejectionCandleHigh = iHigh(_Symbol,_timeFrame,1) ;
|
||||
double rejectionCandleHigherWickSize ;
|
||||
double rejectionCandleBodySize ;
|
||||
|
||||
if( rejectionCandleClose > rejectionCandleOpen ){ // the previous candle closed bullish
|
||||
rejectionCandleHigherWickSize = rejectionCandleHigh - rejectionCandleClose;
|
||||
rejectionCandleBodySize = rejectionCandleClose - rejectionCandleOpen;
|
||||
if(rejectionCandleBodySize >= rejectionCandleHigherWickSize){
|
||||
return true ;
|
||||
}
|
||||
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
@@ -0,0 +1,592 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BuyTradeManager.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
//#include <TradeManagersAttributes.mqh>
|
||||
//#include <Telegram_Handler.mqh>
|
||||
#include <Trade/Trade.mqh>
|
||||
CTrade tradeLongInTradeManager;
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
class BuyTradeManager
|
||||
{
|
||||
private:
|
||||
int tradeId;
|
||||
ulong rejectionByOneCandleTradeArray[3];
|
||||
|
||||
string firstSecureMethod ;
|
||||
bool firstSecureMethodFound;
|
||||
int numberOfTakeProfits ;
|
||||
bool securedFirstLevelProfit ;
|
||||
bool securedSecondLevelProfit;
|
||||
double partialToClose ;
|
||||
bool isTradeRunning ;
|
||||
|
||||
|
||||
public:
|
||||
BuyTradeManager();
|
||||
~BuyTradeManager();
|
||||
|
||||
void fillRejectionByOneCandleTradeArray(int _index, int _id) {rejectionByOneCandleTradeArray[_index] = _id ;}
|
||||
ulong getRejectionByOneCandleTradeTicket(int _index) {return rejectionByOneCandleTradeArray[_index] ;}
|
||||
void printRejectionByOneCandleTradeArray();
|
||||
|
||||
void checkAndSecureTradeIfNeeded(double _ratio, double _riskInDollars);
|
||||
string findFirstSecureMethod();
|
||||
|
||||
bool reachedProfitRatio(int _indexInArr);
|
||||
bool closeTrade(int _indexInArr);
|
||||
bool positionBreakEven(int _indexInArr);
|
||||
|
||||
|
||||
void addTpAtIndex(int _index, double tpPrice) {tpArray[_index] = tpPrice;}
|
||||
int countRemainingTakeProfits();
|
||||
bool reachedClosestTakeProfit();
|
||||
void deleteClosestTp();
|
||||
int findClosestTpIndex();
|
||||
|
||||
|
||||
void cleanOrderDataStructures();
|
||||
|
||||
void setTradeRunning(bool _setting) {isTradeRunning = _setting ;}
|
||||
bool tradeIsRunning() {return isTradeRunning ;}
|
||||
|
||||
double tpArray[3];
|
||||
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyTradeManager::BuyTradeManager()
|
||||
{
|
||||
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
tpArray[i] = -1;
|
||||
}
|
||||
securedFirstLevelProfit = false ;
|
||||
securedSecondLevelProfit = false ;
|
||||
firstSecureMethodFound = false ;
|
||||
firstSecureMethod = "NOT_FOUND" ;
|
||||
partialToClose = -1 ;
|
||||
isTradeRunning = false ;
|
||||
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyTradeManager::~BuyTradeManager()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void BuyTradeManager:: printRejectionByOneCandleTradeArray()
|
||||
{
|
||||
|
||||
Print("Printing the tickets :");
|
||||
for(int i=0 ; i<3 ; i++)
|
||||
{
|
||||
Print((int)rejectionByOneCandleTradeArray[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void BuyTradeManager:: checkAndSecureTradeIfNeeded(double _ratio, double _riskInDollars)
|
||||
{
|
||||
if(securedFirstLevelProfit == false) // in this case im searching for 2 cases: either RR 1:1.5 , OR reaching the first TP , if any of them happened im gonna close half the order and updatae the remaining stop losses
|
||||
{
|
||||
|
||||
|
||||
if(!firstSecureMethodFound)
|
||||
{
|
||||
|
||||
firstSecureMethod = findFirstSecureMethod();
|
||||
if(firstSecureMethod != "FAILED")
|
||||
{
|
||||
|
||||
firstSecureMethodFound = true ;
|
||||
}
|
||||
else
|
||||
if(firstSecureMethod == "FAILED")
|
||||
{
|
||||
Print("Failed to find the first secure method, go check the function : findFirstSecureMehod() !");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(firstSecureMethodFound == true)
|
||||
{
|
||||
|
||||
if(firstSecureMethod == "RATIO_METHOD")
|
||||
{
|
||||
cleanOrderDataStructures(); // this is used each time before we are choosing an order by ticket
|
||||
if(reachedProfitRatio(0))
|
||||
{
|
||||
ChartRedraw(); // Make sure the chart is up to date
|
||||
//ChartScreenShot(0, fileName, 1024, 768, ALIGN_RIGHT);
|
||||
//SendTelegramMessage(TelegramApiUrl, TelegramBotToken, ChatId,
|
||||
//"If you see this message it means we reached the first secure method, which is ratio method, after this message, half of the order must be closed (2 trades will remain active), and the first quarter will be put into Break even " + TimeToString(TimeLocal()), fileName);
|
||||
if(closeTrade(0)) // close the half
|
||||
{
|
||||
|
||||
rejectionByOneCandleTradeArray[0] = -1;
|
||||
Print("Closed Half Of the position due to reaching the first secure Ratio!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed Closing Half of the order by reaching the first secure Ratio !");
|
||||
}
|
||||
|
||||
cleanOrderDataStructures(); // this is used each time before we are choosing an order by ticket
|
||||
if(positionBreakEven(1)) // put the first quarter at break even
|
||||
{
|
||||
|
||||
Print(" First quarter has been put into break even due to reaching the first secure Ratio!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to Put the first quarter into break even");
|
||||
}
|
||||
|
||||
numberOfTakeProfits = countRemainingTakeProfits();
|
||||
|
||||
Print("Number of remaining tps is: " + numberOfTakeProfits);
|
||||
|
||||
securedFirstLevelProfit = true ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
if(firstSecureMethod == "FIRST_TP_METHOD")
|
||||
{
|
||||
if(countRemainingTakeProfits() > 1) // there is at least 2 tp in the tp Array (because if this is the last tp then we want to close the whole order and not just a part of it)
|
||||
{
|
||||
if(reachedClosestTakeProfit()) // 2. Check if reached the first Tp
|
||||
{
|
||||
ChartRedraw(); // Make sure the chart is up to date
|
||||
//ChartScreenShot(0, fileName, 1024, 768, ALIGN_RIGHT);
|
||||
//SendTelegramMessage(TelegramApiUrl, TelegramBotToken, ChatId,
|
||||
//"If you see this message it means we reached the first secure method which is tp1, after this message, half of the order must be closed (2 trades will remain active), and the first quarter will be put into Break even " + TimeToString(TimeLocal()), fileName);
|
||||
// close the first half and update remaining partials sl's and delete the closest take profit from the array
|
||||
cleanOrderDataStructures(); // this is used each time before we are choosing an order by ticket
|
||||
if(closeTrade(0)) // close the half
|
||||
{
|
||||
|
||||
rejectionByOneCandleTradeArray[0] = -1;
|
||||
Print("Closed Half Of the position due to reaching the first TP!");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed Closing Half of the order by reaching the first TP !");
|
||||
}
|
||||
cleanOrderDataStructures(); // this is used each time before we are choosing an order by ticket
|
||||
if(positionBreakEven(1)) // put the first quarter at break even
|
||||
{
|
||||
|
||||
Print(" First quarter has been put into break even due to reaching the first TP!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to Put the first quarter into break even");
|
||||
}
|
||||
deleteClosestTp();
|
||||
numberOfTakeProfits = countRemainingTakeProfits(); // update the number of remaining take profits
|
||||
// calculate the remaining tps
|
||||
|
||||
Print("Number of remaining tps is: " + numberOfTakeProfits);
|
||||
Print("TP ARRY: " + tpArray[0] + ", " + tpArray[1] + " , " + tpArray[2]);
|
||||
|
||||
securedFirstLevelProfit = true ;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
if(numberOfTakeProfits = countRemainingTakeProfits() == 1)
|
||||
{
|
||||
if(reachedClosestTakeProfit())
|
||||
{
|
||||
// close everything remained
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
if(securedFirstLevelProfit == true) // after securing the first level i just want to close the remaining partials by reaching the tp's
|
||||
{
|
||||
|
||||
if(countRemainingTakeProfits() == 1)
|
||||
{
|
||||
if(reachedClosestTakeProfit())
|
||||
{
|
||||
// close everything
|
||||
cleanOrderDataStructures();
|
||||
for(int i=0 ; i<3 ; i++)
|
||||
{
|
||||
closeTrade(i);
|
||||
}
|
||||
Print("Closed every thing because price reached the last Take Profit !");
|
||||
|
||||
ChartRedraw(); // Make sure the chart is up to date
|
||||
//ChartScreenShot(0, fileName, 1024, 768, ALIGN_RIGHT);
|
||||
//SendTelegramMessage(TelegramApiUrl, TelegramBotToken, ChatId,
|
||||
// "If you see this message it means that all order are closed as a result of reaching the last tp " + TimeToString(TimeLocal()), fileName);
|
||||
deleteClosestTp();
|
||||
}
|
||||
}
|
||||
else
|
||||
if(countRemainingTakeProfits() > 1)
|
||||
{
|
||||
if(reachedClosestTakeProfit())
|
||||
{
|
||||
cleanOrderDataStructures();
|
||||
if(PositionSelectByTicket(rejectionByOneCandleTradeArray[1])) // DEALING WITH THE FIRST QUARTER
|
||||
{
|
||||
double currentLot = PositionGetDouble(POSITION_VOLUME);
|
||||
if(partialToClose == -1)
|
||||
{
|
||||
partialToClose = currentLot/numberOfTakeProfits ;
|
||||
}
|
||||
if(tradeLongInTradeManager.PositionClosePartial(rejectionByOneCandleTradeArray[1],NormalizeDouble(partialToClose,2)))
|
||||
{
|
||||
uint res = tradeLongInTradeManager.ResultRetcode();
|
||||
if(res == 10009)
|
||||
{
|
||||
Print("Closed Partials successfully on the first quarter !");
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("The returned code is: " + res + " go check what it means !");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to select position by ticket! , Error: " + GetLastError());
|
||||
Print("The EA tried to close partials on the first quarter, but it is closed, probably due to break even and thats why it couldnt select the order !");
|
||||
}
|
||||
|
||||
|
||||
cleanOrderDataStructures();
|
||||
if(PositionSelectByTicket(rejectionByOneCandleTradeArray[2])) // DEALING WITH THE SECOND QUARTER
|
||||
{
|
||||
if(PositionGetDouble(POSITION_SL) < PositionGetDouble(POSITION_PRICE_OPEN)) // this is to put the second quarter at break even if its not already at break even
|
||||
{
|
||||
positionBreakEven(2);
|
||||
|
||||
}
|
||||
double currentLot = PositionGetDouble(POSITION_VOLUME);
|
||||
if(partialToClose == -1)
|
||||
{
|
||||
partialToClose = currentLot/numberOfTakeProfits ;
|
||||
}
|
||||
if(tradeLongInTradeManager.PositionClosePartial(rejectionByOneCandleTradeArray[2],NormalizeDouble(partialToClose,2)))
|
||||
{
|
||||
uint res = tradeLongInTradeManager.ResultRetcode();
|
||||
if(res == 10009)
|
||||
{
|
||||
Print("Closed Partials successfully on the second quarter!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("The returned code is: " + res + " go check what it means !");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
deleteClosestTp();
|
||||
Print("Number Of Remained tps is: " + countRemainingTakeProfits());
|
||||
|
||||
ChartRedraw(); // Make sure the chart is up to date
|
||||
//ChartScreenShot(0, fileName, 1024, 768, ALIGN_RIGHT);
|
||||
//SendTelegramMessage(TelegramApiUrl, TelegramBotToken, ChatId,
|
||||
// "If you see this message it means we reached a tp level (different than the first secure level), so partial positions will be closed, and the scond quarter must be in break even!" + TimeToString(TimeLocal()), fileName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
string BuyTradeManager:: findFirstSecureMethod()
|
||||
{
|
||||
|
||||
cleanOrderDataStructures(); // this is used each time before we are choosing an order by ticket
|
||||
if(PositionSelectByTicket(rejectionByOneCandleTradeArray[0]))
|
||||
{
|
||||
double positionStopLoss = PositionGetDouble(POSITION_SL);
|
||||
double positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
double firstTakeProfit = tpArray[findClosestTpIndex()];
|
||||
if(((firstTakeProfit-positionOpenPrice)/(positionOpenPrice-positionStopLoss) > firstSecureRatio)) // firstTp > ratio
|
||||
{
|
||||
Print("Found the first profit secure method !");
|
||||
Print("The first TP RR is: 1:" + (firstTakeProfit-positionOpenPrice)/(positionOpenPrice-positionStopLoss) + "the firstSecureRatio is: 1:" + firstSecureRatio);
|
||||
Print("The tp ratio is greater than the firstSecure so:");
|
||||
Print("The first secure method is RATIO_METHOD");
|
||||
return"RATIO_METHOD";
|
||||
}
|
||||
else
|
||||
if((firstTakeProfit-positionOpenPrice)/(positionOpenPrice-positionStopLoss)< firstSecureRatio)
|
||||
{
|
||||
Print("Found the first profit secure method !");
|
||||
Print("The first TP RR is: 1:" + (firstTakeProfit-positionOpenPrice)/(positionOpenPrice-positionStopLoss) + "the firstSecureRatio is: 1:" + firstSecureRatio);
|
||||
Print("The tp ratio is less than the firstSecure so:");
|
||||
Print("The first secure method is FIRST_TP_METHOD");
|
||||
return "FIRST_TP_METHOD" ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to select position by ticket 1, Error: " + GetLastError());
|
||||
}
|
||||
|
||||
return "FAILED" ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool BuyTradeManager:: reachedProfitRatio(int _indexInArr)
|
||||
{
|
||||
|
||||
ulong _ticket = rejectionByOneCandleTradeArray[_indexInArr];
|
||||
if(_ticket != -1)
|
||||
{
|
||||
if(PositionSelectByTicket(_ticket))
|
||||
{
|
||||
if(PositionGetDouble(POSITION_PROFIT)/(0.5*riskDollars) >= firstSecureRatio) // checking if the first half of the contract reached the ratio of first secure profit
|
||||
{
|
||||
Print("reached profit ratio !");
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to select the position by ticket 4 ,Error: " + GetLastError());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool BuyTradeManager:: closeTrade(int _indexInArr)
|
||||
{
|
||||
|
||||
|
||||
ulong _ticket = rejectionByOneCandleTradeArray[_indexInArr];
|
||||
if(_ticket != -1)
|
||||
{
|
||||
if(PositionSelectByTicket(_ticket))
|
||||
{
|
||||
|
||||
// close the first half and update remaining partials sl's
|
||||
if(tradeLongInTradeManager.PositionClose(_ticket))
|
||||
{
|
||||
return true ;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Print("Failed to close positon, Error:" + GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Print("Failed to select position by ticket , Error: "+ GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool BuyTradeManager:: positionBreakEven(int _indexInArr)
|
||||
{
|
||||
|
||||
ulong _ticket = rejectionByOneCandleTradeArray[_indexInArr];
|
||||
if(_ticket != -1)
|
||||
{
|
||||
if(PositionSelectByTicket(_ticket)) // select the first quarter
|
||||
{
|
||||
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
double positionTp = PositionGetDouble(POSITION_TP);
|
||||
double positionSl = PositionGetDouble(POSITION_SL);
|
||||
|
||||
if(tradeLongInTradeManager.PositionModify(_ticket,openPrice,positionTp))
|
||||
{
|
||||
|
||||
|
||||
return true ;
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to modify oder , ERROR: " + GetLastError());
|
||||
return false ;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to select position by ticket ");
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int BuyTradeManager:: countRemainingTakeProfits()
|
||||
{
|
||||
|
||||
int counter = 0 ;
|
||||
for(int i=0; i<3 ; i++)
|
||||
{
|
||||
if(tpArray[i] != -1)
|
||||
{
|
||||
counter++ ;
|
||||
}
|
||||
}
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void BuyTradeManager:: deleteClosestTp()
|
||||
{
|
||||
|
||||
int closestTpIndex =findClosestTpIndex();
|
||||
tpArray[closestTpIndex] = -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int BuyTradeManager:: findClosestTpIndex()
|
||||
{
|
||||
int closestTpIndex = 0;
|
||||
int closestTpValue = 1000000 ; // dummy value
|
||||
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
if(tpArray[i] != -1 && tpArray[i] < closestTpValue)
|
||||
{
|
||||
closestTpValue = tpArray[i];
|
||||
closestTpIndex = i ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return closestTpIndex ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool BuyTradeManager:: reachedClosestTakeProfit()
|
||||
{
|
||||
|
||||
|
||||
double closestTakeProfitValue = tpArray[findClosestTpIndex()];
|
||||
//Print("im in reached closest take profit function ,the current price is: " + SymbolInfoDouble(_Symbol, SYMBOL_BID) + " and the tp is: " + closestTakeProfitValue);
|
||||
if(SymbolInfoDouble(_Symbol, SYMBOL_BID) >= closestTakeProfitValue) // we are looking for the BID , because reaching a tp in a buy trade means we are selling, so we want our take profit value, to be at least as the BID price (because we want to find someone to buy it from us at this price)
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void BuyTradeManager:: cleanOrderDataStructures()
|
||||
{
|
||||
// this is to make sure, that every closed order is removed from the data strucutre !
|
||||
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
if(!PositionSelectByTicket(rejectionByOneCandleTradeArray[i]))
|
||||
{
|
||||
if(GetLastError() == 4753)
|
||||
{
|
||||
rejectionByOneCandleTradeArray[i] = -1 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BuyTradeManagerTiger.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
class BuyTradeManagerTiger
|
||||
{
|
||||
private:
|
||||
|
||||
ulong tradeId ;
|
||||
string entryType ;
|
||||
bool firstPartialSecured ;
|
||||
bool secondPartialSecured ;
|
||||
bool managedRisk ;
|
||||
bool retestWickFormed ;
|
||||
double retestWickLengthInPips ;
|
||||
|
||||
int riskManagementCandleCounter ;
|
||||
double brokenResistanceLowerEdge ;
|
||||
double brokenResistanceHigherEdge ;
|
||||
public:
|
||||
|
||||
ulong getTradeId(){return tradeId ;}
|
||||
|
||||
bool riskAlreadyManaged(){return managedRisk ;}
|
||||
void manageRisk(){managedRisk = true ;}
|
||||
|
||||
bool firstPartialIsSecured(){return firstPartialSecured ;}
|
||||
void secureFirstPartial(){firstPartialSecured = true ;}
|
||||
|
||||
void setBrokenResistancetLowerEdge(double _brokenResistanceLowerEdge){brokenResistanceLowerEdge = _brokenResistanceLowerEdge ;}
|
||||
void setBrokenResistanceHigherEdge(double _brokenResistanceHigherEdge){brokenResistanceHigherEdge = _brokenResistanceHigherEdge ;}
|
||||
|
||||
double getBrokenResistanceLowerEdge(){return brokenResistanceLowerEdge ;}
|
||||
double getBrokenResistanceHigherEdge(){return brokenResistanceHigherEdge ;}
|
||||
|
||||
void incrementRiskManagementCandleCoutner(){riskManagementCandleCounter++ ;}
|
||||
void decrementRiskManagementCandleCounter(){riskManagementCandleCounter-- ;}
|
||||
|
||||
int getRiskManagementCandleCounter(){return riskManagementCandleCounter ;}
|
||||
|
||||
void setRiskManagementCandleCounter(int count){ riskManagementCandleCounter = count ;}
|
||||
|
||||
BuyTradeManagerTiger(ulong _tradeId);
|
||||
~BuyTradeManagerTiger();
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyTradeManagerTiger::BuyTradeManagerTiger(ulong _tradeId)
|
||||
{
|
||||
|
||||
tradeId = _tradeId ;
|
||||
firstPartialSecured = false ;
|
||||
secondPartialSecured = false ;
|
||||
managedRisk = false ;
|
||||
retestWickFormed = false ;
|
||||
retestWickLengthInPips = 0 ;
|
||||
|
||||
riskManagementCandleCounter = 0 ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
BuyTradeManagerTiger::~BuyTradeManagerTiger()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,333 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| TigerObserver.mq5 |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
|
||||
#include "Algo_Skeleton_Functions.mqh"
|
||||
|
||||
long H4_SUPPORT_ZONE_CLR ;
|
||||
long H4_RESISTANCE_ZONE_CLR ;
|
||||
long H1_SUPPORT_ZONE_CLR;
|
||||
long H1_RESISTANCE_ZONE_CLR;
|
||||
long M30_SUPPORT_ZONE_CLR ;
|
||||
long M30_RESISTANCE_ZONE_CLR ;
|
||||
|
||||
int OnInit()
|
||||
{
|
||||
//--- create timer
|
||||
EventSetTimer(60);
|
||||
|
||||
// ONLY FOR VISULAZITAION ON STRATEGY TESTER
|
||||
iClose(_Symbol,PERIOD_W1,1);
|
||||
iClose(_Symbol,PERIOD_D1,1);
|
||||
iClose(_Symbol,PERIOD_H4,5);
|
||||
iClose(_Symbol,PERIOD_H1,5);
|
||||
iClose(_Symbol,PERIOD_M30,5);
|
||||
iClose(_Symbol,PERIOD_M15,5);
|
||||
|
||||
H4_SUPPORT_ZONE_CLR = clrBlack ;
|
||||
H4_RESISTANCE_ZONE_CLR = clrBlack ;
|
||||
|
||||
if(ENTRY_BASED_H1_STRUCTURE == true && ENTRY_BASED_M30_STRUCTURE == false){
|
||||
M30_SUPPORT_ZONE_CLR = clrBlack ;
|
||||
M30_RESISTANCE_ZONE_CLR = clrBlack ;
|
||||
|
||||
H1_SUPPORT_ZONE_CLR = clrAliceBlue ;
|
||||
H1_RESISTANCE_ZONE_CLR = clrDarkGray ;
|
||||
|
||||
}
|
||||
else if(ENTRY_BASED_H1_STRUCTURE == false && ENTRY_BASED_M30_STRUCTURE == true){
|
||||
M30_SUPPORT_ZONE_CLR = clrAliceBlue ;
|
||||
M30_RESISTANCE_ZONE_CLR = clrDarkGray ;
|
||||
|
||||
H1_SUPPORT_ZONE_CLR = clrBlack ;
|
||||
H1_RESISTANCE_ZONE_CLR = clrBlack ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
objectsManager.addTextTiger();
|
||||
|
||||
for(int i=0; i<NUM_MAX_ALLOWED_TRADES ; i++)
|
||||
{
|
||||
BuyActiveTradesArray[i] = NULL ;
|
||||
SellActiveTradesArray[i] = NULL ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//objectsManager.addMarketDescriptionTextTiger();
|
||||
|
||||
//---
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- destroy timer
|
||||
Print("Buys Count: " + buysCount);
|
||||
Print("Sells Count: " + sellsCount);
|
||||
EventKillTimer();
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//---
|
||||
|
||||
cleanBuyTradesArr();
|
||||
cleanSellTradesArr();
|
||||
secureProfitIfNeeded();
|
||||
|
||||
if(newCandleDetectorM15.isNewCandle())
|
||||
{
|
||||
|
||||
// UPDATING M30 ZONES
|
||||
if(zoneContainerSupport_M30.getNumberOfActiveZones()>0){
|
||||
updateNormalZonesSupport(zoneContainerSupport_M30,PERIOD_M30,"PERIOD_M30",M30_SUPPORT_ZONE_CLR,rangeDistanceBetweenZonesActual_M30,0);
|
||||
}
|
||||
|
||||
if(zoneContainer_M30.getNumberOfActiveZones()> 0){
|
||||
updateNormalZonesResistance(zoneContainer_M30,PERIOD_M30,"PERIOD_M30",M30_RESISTANCE_ZONE_CLR,rangeDistanceBetweenZonesActual_M30,0);
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
if(newCandleDetector30M.isNewCandle())
|
||||
{
|
||||
|
||||
if(trail_based_m30){
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_M30);
|
||||
}
|
||||
datetime currTime = TimeCurrent();
|
||||
ObjectSetString(0,"clockTextTiger",OBJPROP_TEXT,TimeToString(currTime,TIME_MINUTES));
|
||||
|
||||
detectAndDrawResistanceOnTimeFrame(PERIOD_M30,"PERIOD_M30",M30_RESISTANCE_ZONE_CLR,zoneContainer_M30,rangeDistanceBetweenZonesActual_M30,0);
|
||||
detectAndDrawSupportOnTimeFrame(PERIOD_M30,"PERIOD_M30",M30_SUPPORT_ZONE_CLR,zoneContainerSupport_M30,rangeDistanceBetweenZonesActual_M30,0);
|
||||
if(ENTRY_BASED_M30_STRUCTURE){
|
||||
|
||||
handleBuys(zoneContainer_M30,PERIOD_M30,"PERIOD_M30",cleanRangeUponEntryActual);
|
||||
handleSells(zoneContainerSupport_M30,PERIOD_M30,"PERIOD_M30",cleanRangeUponEntryActual);
|
||||
}
|
||||
else{
|
||||
|
||||
handleBullishBreakouts(zoneContainer_M30,PERIOD_M30,"PERIOD_M30");
|
||||
handleBearishBreakouts(zoneContainerSupport_M30,PERIOD_M30,"PERIOD_M30");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// UPDATING H1 ZONES
|
||||
if(zoneContainerSupport_H1.getNumberOfActiveZones()>0){
|
||||
updateNormalZonesSupport(zoneContainerSupport_H1,PERIOD_H1,"PERIOD_H1",H1_SUPPORT_ZONE_CLR,rangeDistanceBetweenZonesActual_H1,1000);
|
||||
}
|
||||
|
||||
if(zoneContainer_H1.getNumberOfActiveZones()> 0){
|
||||
updateNormalZonesResistance(zoneContainer_H1,PERIOD_H1,"PERIOD_H1",H1_RESISTANCE_ZONE_CLR,rangeDistanceBetweenZonesActual_H1,1000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
zoneContainerSupport_M30.printZonesSortedArray();
|
||||
zoneContainer_M30.printZonesSortedArray();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
if(newCandleDetector1H.isNewCandle()){
|
||||
|
||||
if(trail_based_h1){
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_H1);
|
||||
}
|
||||
|
||||
|
||||
detectAndDrawResistanceOnTimeFrame(PERIOD_H1,"PERIOD_H1",H1_RESISTANCE_ZONE_CLR,zoneContainer_H1,rangeDistanceBetweenZonesActual_H1,1000);
|
||||
detectAndDrawSupportOnTimeFrame(PERIOD_H1,"PERIOD_H1",H1_SUPPORT_ZONE_CLR,zoneContainerSupport_H1,rangeDistanceBetweenZonesActual_H1,1000);
|
||||
|
||||
if(ENTRY_BASED_H1_STRUCTURE){
|
||||
|
||||
handleBuys(zoneContainer_H1,PERIOD_H1,"PERIOD_H1",cleanRangeUponEntryActual);
|
||||
handleSells(zoneContainerSupport_H1,PERIOD_H1,"PERIOD_H1",cleanRangeUponEntryActual);
|
||||
}
|
||||
|
||||
else{
|
||||
handleBullishBreakouts(zoneContainer_H1,PERIOD_H1,"PERIOD_H1");
|
||||
handleBearishBreakouts(zoneContainerSupport_H1,PERIOD_H1,"PERIOD_H1");
|
||||
|
||||
}
|
||||
|
||||
|
||||
// UPDATING H4 ZONES
|
||||
if(zoneContainerSupport_H4.getNumberOfActiveZones()>0){
|
||||
updateNormalZonesSupport(zoneContainerSupport_H4,PERIOD_H4,"PERIOD_H4",H4_SUPPORT_ZONE_CLR,rangeDistanceBetweenZonesActual_H4,2000);
|
||||
}
|
||||
|
||||
if(zoneContainer_H4.getNumberOfActiveZones()> 0){
|
||||
updateNormalZonesResistance(zoneContainer_H4,PERIOD_H4,"PERIOD_H4",H4_RESISTANCE_ZONE_CLR,rangeDistanceBetweenZonesActual_H4,2000);
|
||||
}
|
||||
|
||||
Print("H1 zones :");
|
||||
//zoneContainerSupport_H1.printZonesSortedArray();
|
||||
//zoneContainer_H1.printZonesSortedArray();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if(newCandleDetector4H.isNewCandle()){
|
||||
last_H4_candle_broke_structure = false ;
|
||||
|
||||
if(trail_based_h4){
|
||||
trailAllOpenPositionsIfNeeded(PERIOD_H4);
|
||||
}
|
||||
|
||||
|
||||
detectAndDrawResistanceOnTimeFrame(PERIOD_H4,"PERIOD_H4",H4_RESISTANCE_ZONE_CLR,zoneContainer_H4,rangeDistanceBetweenZonesActual_H4,2000);
|
||||
detectAndDrawSupportOnTimeFrame(PERIOD_H4,"PERIOD_H4",H4_SUPPORT_ZONE_CLR,zoneContainerSupport_H4,rangeDistanceBetweenZonesActual_H4,2000);
|
||||
|
||||
// BREAK OF STRUCTURE HANDLING
|
||||
|
||||
|
||||
handleBullishBreakouts(zoneContainer_H4,PERIOD_H4,"PERIOD_H4");
|
||||
handleBearishBreakouts(zoneContainerSupport_H4,PERIOD_H4,"PERIOD_H4");
|
||||
|
||||
//handleBuys(zoneContainer_H4,PERIOD_H4,"PERIOD_H4",cleanRangeUponEntryActual);
|
||||
//handleSells(zoneContainerSupport_H4,PERIOD_H4,"PERIOD_H4",cleanRangeUponEntryActual);
|
||||
|
||||
//Print("H4, Zones:");
|
||||
//zoneContainerSupport_H4.printZonesSortedArray();
|
||||
//zoneContainer_H4.printZonesSortedArray();
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(newCandleDetectorDaily.isNewCandle())
|
||||
{
|
||||
|
||||
//detectAndDrawResistanceOnTimeFrame(PERIOD_D1,"PERIOD_D1",clrYellow,clrYellow,zoneContainer_D1);
|
||||
//updateBreakAboveStructureAndDelete(zoneContainer_D1,PERIOD_D1,"PERIOD_D1");
|
||||
objectsManager.drawVerticalLine(clrAqua, TimeCurrent());
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
if(newCandleDetectorWeekly.isNewCandle())
|
||||
{
|
||||
|
||||
objectsManager.drawVerticalLine(clrRed, TimeCurrent());
|
||||
|
||||
weekCounter++ ;
|
||||
|
||||
if(weekCounter == deleteAllZonesAfter_Weeks){
|
||||
|
||||
//deleteAllzonesWithGUI();
|
||||
weekCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Timer function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTimer()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Trade function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTrade()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TradeTransaction function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTradeTransaction(const MqlTradeTransaction& trans,
|
||||
const MqlTradeRequest& request,
|
||||
const MqlTradeResult& result)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Tester function |
|
||||
//+------------------------------------------------------------------+
|
||||
double OnTester()
|
||||
{
|
||||
//---
|
||||
double ret=0.0;
|
||||
//---
|
||||
|
||||
//---
|
||||
return(ret);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterInit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterInit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterPass function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterPass()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterDeinit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterDeinit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnChartEvent(const int id,
|
||||
const long &lparam,
|
||||
const double &dparam,
|
||||
const string &sparam)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| BookEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnBookEvent(const string &symbol)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,363 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Gandalf.mq5 |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#include "GraphicalObjectsManager.mqh"
|
||||
#include "TempLineObjectAttributes.mqh"
|
||||
#include "ObjectConfirmationUnit.mqh"
|
||||
#include "BuyGandalf.mqh"
|
||||
#include "SellGandalf.mqh"
|
||||
#include "LotSizeCalculator.mqh"
|
||||
|
||||
|
||||
|
||||
LotSizeCalculator lsCalc;
|
||||
GraphicalObjectsManager graphicalObjectsManager ;
|
||||
ObjectConfirmationUnit objectConfUnit ;
|
||||
BuyGandalf buyGandalfGray ;
|
||||
SellGandalf SellGandalfGray ;
|
||||
|
||||
bool buyCase = false ;
|
||||
bool sellCase = false ;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
TempLineObjectAttributes tempLineObjectAttr ;
|
||||
int OnInit()
|
||||
{
|
||||
//--- create timer
|
||||
EventSetTimer(60);
|
||||
|
||||
|
||||
graphicalObjectsManager.addTotalRiskText();
|
||||
graphicalObjectsManager.addTakeBuyTradeButton();
|
||||
graphicalObjectsManager.addTakeSellTradeButton();
|
||||
graphicalObjectsManager.addText();
|
||||
graphicalObjectsManager.addConfirmButton();
|
||||
|
||||
//ObjectSetString(0,"totalRiskText",OBJPROP_TEXT,"the new ext is : !");
|
||||
|
||||
|
||||
|
||||
//---
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- destroy timer
|
||||
EventKillTimer();
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
|
||||
updateOverAllRiskText();
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Timer function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTimer()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Trade function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTrade()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TradeTransaction function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTradeTransaction(const MqlTradeTransaction& trans,
|
||||
const MqlTradeRequest& request,
|
||||
const MqlTradeResult& result)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Tester function |
|
||||
//+------------------------------------------------------------------+
|
||||
double OnTester()
|
||||
{
|
||||
//---
|
||||
double ret=0.0;
|
||||
//---
|
||||
|
||||
//---
|
||||
return(ret);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterInit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterInit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterPass function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterPass()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| TesterDeinit function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTesterDeinit()
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnChartEvent(const int id,
|
||||
const long &lparam,
|
||||
const double &dparam,
|
||||
const string &sparam)
|
||||
{
|
||||
|
||||
|
||||
|
||||
switch(id)
|
||||
{
|
||||
|
||||
case CHARTEVENT_CLICK:
|
||||
{
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//--- clicking on a graphical object
|
||||
case CHARTEVENT_OBJECT_CLICK:
|
||||
{
|
||||
|
||||
|
||||
if(sparam == "BUY_BTN")
|
||||
{
|
||||
buyCase = true ;
|
||||
|
||||
graphicalObjectsManager.drawStopLossLineGandalf();
|
||||
objectConfUnit.setWaitingStatus(true);
|
||||
|
||||
}
|
||||
|
||||
else if(sparam == "SELL_BTN"){
|
||||
sellCase = true ;
|
||||
graphicalObjectsManager.drawStopLossLineGandalf();
|
||||
objectConfUnit.setWaitingStatus(true);
|
||||
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
if(sparam == "CONFIRM_BTN")
|
||||
{
|
||||
if(buyCase == true)
|
||||
{
|
||||
if(objectConfUnit.getWaitingStatus() == true) // THIS IS TO MAKE SURE THAT THERE IS SOMETHING SELECTED TO BE CONFIRMED
|
||||
{
|
||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK) ;
|
||||
string textRecieved;
|
||||
graphicalObjectsManager.EditTextGet(textRecieved,0,"textName");
|
||||
double riskAsDouble = StringToDouble(textRecieved);
|
||||
|
||||
double stopLossPrice = tempLineObjectAttr.getPrice();
|
||||
|
||||
|
||||
|
||||
if(ObjectDelete(_Symbol,"sl"))
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Failed to delete the stop loss line ! Error: "+ GetLastError());
|
||||
}
|
||||
|
||||
//Print("Buy info has been set, SL price: " + stopLossPrice + " risk is: " + riskAsDouble);
|
||||
|
||||
double lotsToTrade = lsCalc.calculateLotSize(riskAsDouble,stopLossPrice);
|
||||
|
||||
buyGandalfGray.takeBuyTradeGandalf(lotsToTrade,stopLossPrice);
|
||||
|
||||
objectConfUnit.setWaitingStatus(false);
|
||||
buyCase = false ;
|
||||
|
||||
// change the risk text
|
||||
//updateOverAllRiskText();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
if(sellCase == true)
|
||||
{
|
||||
|
||||
if(objectConfUnit.getWaitingStatus() == true) // THIS IS TO MAKE SURE THAT THERE IS SOMETHING SELECTED TO BE CONFIRMED
|
||||
{
|
||||
|
||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
string textRecieved;
|
||||
graphicalObjectsManager.EditTextGet(textRecieved,0,"textName");
|
||||
double riskAsDouble = StringToDouble(textRecieved);
|
||||
|
||||
double stopLossPrice = tempLineObjectAttr.getPrice();
|
||||
|
||||
if(ObjectDelete(_Symbol,"sl")){
|
||||
|
||||
|
||||
}
|
||||
else{
|
||||
|
||||
Print("Failed to delete the stop loss line ! Error: "+ GetLastError());
|
||||
}
|
||||
double lotsToTrade = lsCalc.calculateLotSize(riskAsDouble,stopLossPrice);
|
||||
SellGandalfGray.takeSellTradeGandalf(lotsToTrade,stopLossPrice);
|
||||
|
||||
objectConfUnit.setWaitingStatus(false);
|
||||
sellCase = false ;
|
||||
|
||||
|
||||
// change the risk text
|
||||
//updateOverAllRiskText();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case CHARTEVENT_OBJECT_DRAG:
|
||||
{
|
||||
|
||||
|
||||
|
||||
if(ObjectGetInteger(_Symbol,sparam,OBJPROP_TYPE,0) == OBJ_HLINE)
|
||||
{
|
||||
|
||||
if(StringSubstr(sparam,0,2) == "sl") // case of sl line (attached to a zone)
|
||||
{
|
||||
double stopLossPrice = ObjectGetDouble(_Symbol,sparam,OBJPROP_PRICE,0);
|
||||
tempLineObjectAttr.setId(sparam);
|
||||
tempLineObjectAttr.setPrice(stopLossPrice);
|
||||
}
|
||||
else
|
||||
if(StringSubstr(sparam,0,2) == "tp") // case of tp line (attached to a zone)
|
||||
{
|
||||
double takeProfitPrice = ObjectGetDouble(_Symbol,sparam,OBJPROP_PRICE,0);
|
||||
tempLineObjectAttr.setId(sparam);
|
||||
tempLineObjectAttr.setPrice(takeProfitPrice);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case CHARTEVENT_KEYDOWN:
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| BookEvent function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnBookEvent(const string &symbol)
|
||||
{
|
||||
//---
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
void updateOverAllRiskText(){
|
||||
|
||||
|
||||
|
||||
//double pointValue = lsCalc.PointValue(_Symbol);
|
||||
|
||||
double pointValue = PointValueNew(_Symbol);
|
||||
double overAllRisk = 0 ;
|
||||
for(int i=PositionsTotal() -1 ;i >= 0 ; i--){
|
||||
//Print("entered here !");
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
int positionType = PositionGetInteger(POSITION_TYPE);
|
||||
double positionStopLossPrice = PositionGetDouble(POSITION_SL);
|
||||
double positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
double positionLotSize = PositionGetDouble(POSITION_VOLUME);
|
||||
|
||||
|
||||
if(positionType == POSITION_TYPE_BUY){
|
||||
double positionStopLossInPoints = (positionOpenPrice - positionStopLossPrice) * MathPow(10 , SymbolInfoInteger(_Symbol,SYMBOL_DIGITS)) ;
|
||||
double riskAmount = pointValue*positionLotSize*positionStopLossInPoints ;
|
||||
overAllRisk = overAllRisk + riskAmount ;
|
||||
string riskAsString = DoubleToString(overAllRisk);
|
||||
ObjectSetString(0,"totalRiskText",OBJPROP_TEXT,"Total Risk is:" + riskAsString);
|
||||
}
|
||||
else if(positionType == POSITION_TYPE_SELL){
|
||||
double positionStopLossInPoints = (positionStopLossPrice - positionOpenPrice) * MathPow(10 , SymbolInfoInteger(_Symbol,SYMBOL_DIGITS)) ;
|
||||
double riskAmount = pointValue*positionLotSize*positionStopLossInPoints ;
|
||||
overAllRisk = overAllRisk + riskAmount ;
|
||||
string riskAsString = DoubleToString(overAllRisk);
|
||||
ObjectSetString(0,"totalRiskText",OBJPROP_TEXT,"Total Risk is:" + riskAsString);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
double PointValueNew(string symbol){
|
||||
|
||||
|
||||
double tickSize = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE);
|
||||
double tickValue = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_VALUE);
|
||||
double point = SymbolInfoDouble(symbol,SYMBOL_POINT);
|
||||
double ticksPerPoint = tickSize/point ;
|
||||
double pointValue = tickValue/ticksPerPoint ;
|
||||
|
||||
return (pointValue);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,254 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| HighFractal.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
class HighFractal
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
double highPrice ;
|
||||
int leftPeriod;
|
||||
int rightPeriod;
|
||||
|
||||
MqlDateTime dateStruct ;
|
||||
datetime date ;
|
||||
|
||||
double sellLimitPrice; // the fib level price , based on this fractal
|
||||
double lowestPeak ; // the highest price reached, after the fractal was formed
|
||||
int hour ;
|
||||
int minute;
|
||||
int distance ; // holds the number of candles from this fractal until the current live candle
|
||||
string arrowObjName ;
|
||||
double fibPrice ;
|
||||
|
||||
public:
|
||||
HighFractal();
|
||||
HighFractal(double _price, int _leftPeriod, int _rightPeriod, datetime _date,ENUM_TIMEFRAMES _tf);
|
||||
~HighFractal();
|
||||
|
||||
|
||||
|
||||
// GETTERS
|
||||
|
||||
double getPrice();
|
||||
int getLeftPeriod();
|
||||
int getRightPeriod();
|
||||
int getHour();
|
||||
int getMinute();
|
||||
double getLowestPeak();
|
||||
int getDistance();
|
||||
string getArrowObjName();
|
||||
datetime getDate();
|
||||
// SETTERS
|
||||
|
||||
void setPrice(double _price);
|
||||
void setLeftPeriod(int _leftPeriod);
|
||||
void setRightPeriod(int _rightPeriod);
|
||||
void setHour(int _hour);
|
||||
void setMinute(int _minute);
|
||||
void setLowestPeak(double _highest);
|
||||
void setArrowObjName(string _name);
|
||||
void setDistance(int _dist);
|
||||
void setDate(datetime _givenDate);
|
||||
|
||||
|
||||
// OTHER FUNCTIONS
|
||||
|
||||
double calculateFibPrice(double _fibLevel, double _highPrice, double _lowPrice); // calculate the fibonacci price based on the given level, and saves the price in the fibPrice88 variable in the object
|
||||
void updateDistance();
|
||||
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
HighFractal::HighFractal()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
HighFractal::HighFractal(double _price, int _leftPeriod, int _rightPeriod,datetime _date,ENUM_TIMEFRAMES _tf)
|
||||
{
|
||||
// the constructor sets the data to the attribues , and calculates the real time of the fractal , because the given minute and hour
|
||||
// are not the real time, they are the time of when the fractal was "known to be a fractal", which is after _righPeriod amount of candles
|
||||
|
||||
highPrice = _price ;
|
||||
leftPeriod = _leftPeriod;
|
||||
rightPeriod = _rightPeriod;
|
||||
sellLimitPrice = -1 ;
|
||||
distance = _rightPeriod+1;
|
||||
arrowObjName = " " ;
|
||||
lowestPeak = -1;
|
||||
|
||||
|
||||
date = iTime(_Symbol,_tf,_rightPeriod+1); // bring the actual date of the fractal
|
||||
TimeToStruct(date,dateStruct); // convert the actual date into a struct
|
||||
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
HighFractal::~HighFractal()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
double HighFractal:: getPrice()
|
||||
{
|
||||
|
||||
return highPrice ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int HighFractal:: getLeftPeriod()
|
||||
{
|
||||
|
||||
return leftPeriod ;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int HighFractal:: getRightPeriod()
|
||||
{
|
||||
|
||||
return rightPeriod ;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int HighFractal:: getHour()
|
||||
{
|
||||
|
||||
return dateStruct.hour ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int HighFractal:: getMinute()
|
||||
{
|
||||
return dateStruct.min ;
|
||||
}
|
||||
|
||||
|
||||
double HighFractal:: getLowestPeak(){
|
||||
|
||||
return lowestPeak ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int HighFractal:: getDistance(){
|
||||
|
||||
return distance ;
|
||||
}
|
||||
|
||||
|
||||
string HighFractal:: getArrowObjName(){
|
||||
return arrowObjName ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
datetime HighFractal:: getDate(){
|
||||
|
||||
return date ;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void HighFractal:: setPrice(double _price)
|
||||
{
|
||||
highPrice = _price ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void HighFractal:: setLeftPeriod(int _leftPeriod)
|
||||
{
|
||||
leftPeriod = _leftPeriod ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void HighFractal:: setRightPeriod(int _rightPeriod)
|
||||
{
|
||||
rightPeriod = _rightPeriod ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void HighFractal:: setHour(int _hour)
|
||||
{
|
||||
hour = _hour ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void HighFractal:: setMinute(int _minute)
|
||||
{
|
||||
minute = _minute ;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
void HighFractal:: setArrowObjName(string _name){
|
||||
arrowObjName = _name ;
|
||||
|
||||
}
|
||||
|
||||
void HighFractal:: setDistance(int _dist){
|
||||
distance = _dist ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double HighFractal:: calculateFibPrice(double _fibLevel, double _highPrice, double _lowPrice){
|
||||
|
||||
double difference = _lowPrice - _highPrice ;
|
||||
difference = difference*-1 ;
|
||||
double retracement = _fibLevel * difference ;
|
||||
double _fibPrice = _lowPrice + retracement ;
|
||||
fibPrice = _fibPrice ;
|
||||
return fibPrice;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void HighFractal:: setLowestPeak(double _lowest){
|
||||
|
||||
lowestPeak = _lowest ;
|
||||
|
||||
}
|
||||
|
||||
void HighFractal:: setDate(datetime _givenDate){
|
||||
date = _givenDate;
|
||||
TimeToStruct(date,dateStruct); // convert the actual date into a struct
|
||||
}
|
||||
|
||||
void HighFractal:: updateDistance(){
|
||||
|
||||
distance++ ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,131 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| HighFractalContainer.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#include "HighFractal.mqh"
|
||||
#include <library_functions.mqh>
|
||||
#define SIZE 700
|
||||
|
||||
double input arrowDistanceHighs ;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
class HighFractalContainer
|
||||
{
|
||||
private:
|
||||
HighFractal* highFractals[SIZE];
|
||||
int freeIndex ;
|
||||
double range ;
|
||||
ENUM_TIMEFRAMES timeFrame ;
|
||||
public:
|
||||
HighFractalContainer(ENUM_TIMEFRAMES _timeFrame);
|
||||
~HighFractalContainer();
|
||||
|
||||
//GETTERS
|
||||
|
||||
HighFractal* getHighFractal(int _index) {return highFractals[_index] ;} // returns the fractal using its index in the array
|
||||
int getFreeIndex() {return freeIndex ; }
|
||||
|
||||
//SETTERS
|
||||
void setRange(double _range) {range = _range ;}
|
||||
|
||||
// OTHER FUNCTIONS
|
||||
void addHighFractal(HighFractal* _highFractal); // adds high fractal to the high fractals array
|
||||
void printHighFractals(); // prints the data of every high fractal in the highFractals[] array
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
HighFractalContainer::HighFractalContainer(ENUM_TIMEFRAMES _timeFrame)
|
||||
{
|
||||
timeFrame = _timeFrame;
|
||||
freeIndex = 0 ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
HighFractalContainer::~HighFractalContainer()
|
||||
{
|
||||
|
||||
for(int i=0; i<SIZE; i++) // free the highFractals array
|
||||
{
|
||||
delete highFractals[i] ;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
void HighFractalContainer:: addHighFractal(HighFractal* _highFractal){
|
||||
|
||||
|
||||
if(freeIndex == SIZE) // in this case we are adding a new fractal but the array is full so we need to do the following
|
||||
{
|
||||
ObjectDelete(_Symbol,highFractals[0].getArrowObjName()); // delete the object arrow of the deleted fractal
|
||||
|
||||
|
||||
ObjectCreate(_Symbol,_highFractal.getArrowObjName(),OBJ_ARROW_DOWN,0,iTime(Symbol(),timeFrame,_highFractal.getDistance()),iHigh(Symbol(),timeFrame,_highFractal.getDistance()) + arrowDistanceHighs); // create the new object arrow of the new fractal
|
||||
ObjectSetInteger(0,_highFractal.getArrowObjName(),OBJPROP_COLOR,clrWhite);
|
||||
delete highFractals[0]; // free the memory allocated for the fractal in the first index (because we wanna remove it from the array)
|
||||
|
||||
|
||||
for(int i=0; i< SIZE-1 ; i++) // shift the array
|
||||
{
|
||||
|
||||
highFractals[i] = highFractals[i+1];
|
||||
}
|
||||
|
||||
highFractals[freeIndex - 1] = _highFractal ;
|
||||
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
if(freeIndex == 0) // case of the first fractal
|
||||
{
|
||||
|
||||
highFractals[freeIndex] = _highFractal ;
|
||||
freeIndex++;
|
||||
|
||||
ObjectCreate(_Symbol,_highFractal.getArrowObjName(),OBJ_ARROW_DOWN,0,iTime(Symbol(),timeFrame,_highFractal.getDistance()),iHigh(Symbol(),timeFrame,_highFractal.getDistance()) + arrowDistanceHighs);
|
||||
ObjectSetInteger(0,_highFractal.getArrowObjName(),OBJPROP_COLOR,clrWhite);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
highFractals[freeIndex] = _highFractal ;
|
||||
freeIndex++;
|
||||
ObjectCreate(_Symbol,_highFractal.getArrowObjName(),OBJ_ARROW_DOWN,0,iTime(Symbol(),timeFrame,_highFractal.getDistance()),iHigh(Symbol(),timeFrame,_highFractal.getDistance()) + arrowDistanceHighs);
|
||||
ObjectSetInteger(0,_highFractal.getArrowObjName(),OBJPROP_COLOR,clrWhite);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void HighFractalContainer:: printHighFractals()
|
||||
{
|
||||
|
||||
if(freeIndex > 0)
|
||||
{
|
||||
for(int i=0 ; i<freeIndex ; i++)
|
||||
{
|
||||
|
||||
Print(" Fractal " + i + " Time: ", highFractals[i].getHour() + ":" + highFractals[i].getMinute()+ " Price: "
|
||||
+ highFractals[i].getPrice() + " Distance: " + highFractals[i].getDistance() );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| LotSizeCalculator.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
class LotSizeCalculator
|
||||
{
|
||||
private:
|
||||
|
||||
public:
|
||||
LotSizeCalculator();
|
||||
~LotSizeCalculator();
|
||||
|
||||
double calculateLotSize(double riskInMoney,double stopLossPrice);
|
||||
|
||||
|
||||
string BaseCurrency() { return (AccountInfoString(ACCOUNT_CURRENCY)); }
|
||||
double Point(string symbol) { return (SymbolInfoDouble(symbol, SYMBOL_POINT)); }
|
||||
double TickSize(string symbol) { return (SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE)); }
|
||||
double TickValue(string symbol) { return (SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE)); }
|
||||
|
||||
double PointValue(string symbol);
|
||||
|
||||
void Test(string symbol);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
LotSizeCalculator::LotSizeCalculator()
|
||||
{
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
LotSizeCalculator::~LotSizeCalculator()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double LotSizeCalculator:: calculateLotSize(double riskInMoney, double stopLossPrice)
|
||||
{
|
||||
|
||||
double difference ;
|
||||
double differenceInPoints ;
|
||||
|
||||
if(stopLossPrice > SymbolInfoDouble(_Symbol, SYMBOL_BID)) // we are calculating for a sell
|
||||
{
|
||||
difference = stopLossPrice - SymbolInfoDouble(_Symbol, SYMBOL_BID) ;
|
||||
differenceInPoints = difference / SymbolInfoDouble(_Symbol, SYMBOL_POINT);
|
||||
double pointValue = PointValue(_Symbol);
|
||||
|
||||
// Situation 3, fixed risk amount and stop loss, how many lots to trade
|
||||
double riskInPoints = differenceInPoints;
|
||||
double riskLots = riskInMoney / (pointValue * riskInPoints);
|
||||
|
||||
return riskLots;
|
||||
}
|
||||
|
||||
if(SymbolInfoDouble(_Symbol, SYMBOL_ASK) > stopLossPrice){
|
||||
difference = SymbolInfoDouble(_Symbol, SYMBOL_ASK) - stopLossPrice ;
|
||||
differenceInPoints = difference / SymbolInfoDouble(_Symbol, SYMBOL_POINT);
|
||||
double pointValue = PointValue(_Symbol);
|
||||
double riskInPoints = differenceInPoints;
|
||||
double riskLots = riskInMoney / (pointValue * riskInPoints);
|
||||
return riskLots;
|
||||
}
|
||||
|
||||
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double LotSizeCalculator:: PointValue(string symbol)
|
||||
{
|
||||
|
||||
double tickSize = TickSize(symbol);
|
||||
double tickValue = TickValue(symbol);
|
||||
double point = Point(symbol);
|
||||
double ticksPerPoint = tickSize / point;
|
||||
double pointValue = tickValue / ticksPerPoint;
|
||||
|
||||
PrintFormat("tickSize=%f, tickValue=%f, point=%f, ticksPerPoint=%f, pointValue=%f",
|
||||
tickSize, tickValue, point, ticksPerPoint, pointValue);
|
||||
|
||||
return (pointValue);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void LotSizeCalculator:: Test(string symbol)
|
||||
{
|
||||
|
||||
PrintFormat("Base currency is %s", BaseCurrency());
|
||||
PrintFormat("Testing for symbol %s", symbol);
|
||||
|
||||
double pointValue = PointValue(symbol);
|
||||
|
||||
PrintFormat("ValuePerPoint for %s is %f", symbol, pointValue);
|
||||
|
||||
// Situation 3, fixed risk amount and stop loss, how many lots to trade
|
||||
double riskAmount = 100;
|
||||
double riskPoints = 5000;
|
||||
double riskLots = riskAmount / (pointValue * riskPoints);
|
||||
PrintFormat("Risk lots for %s value %f and stop loss at %f points is %f",
|
||||
symbol, riskAmount, riskPoints, riskLots);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,255 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| LowFractal.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
class LowFractal
|
||||
{
|
||||
private:
|
||||
|
||||
private:
|
||||
|
||||
double lowPrice ;
|
||||
int leftPeriod;
|
||||
int rightPeriod;
|
||||
|
||||
MqlDateTime dateStruct ;
|
||||
datetime date ;
|
||||
|
||||
double buyLimitPrice; // the fib level price , based on this fractal
|
||||
double highestPeak ; // the highest price reached, after the fractal was formed
|
||||
int hour ;
|
||||
int minute;
|
||||
int distance ; // holds the number of candles from this fractal until the current live candle
|
||||
string arrowObjName ;
|
||||
double fibPrice ;
|
||||
|
||||
public:
|
||||
LowFractal();
|
||||
LowFractal(double _price, int _leftPeriod, int _rightPeriod, datetime _date,ENUM_TIMEFRAMES _tf);
|
||||
~LowFractal();
|
||||
|
||||
|
||||
|
||||
// GETTERS
|
||||
|
||||
double getPrice();
|
||||
int getLeftPeriod();
|
||||
int getRightPeriod();
|
||||
int getHour();
|
||||
int getMinute();
|
||||
double getHighestPeak();
|
||||
int getDistance();
|
||||
string getArrowObjName();
|
||||
datetime getDate();
|
||||
// SETTERS
|
||||
|
||||
void setPrice(double _price);
|
||||
void setLeftPeriod(int _leftPeriod);
|
||||
void setRightPeriod(int _rightPeriod);
|
||||
void setHour(int _hour);
|
||||
void setMinute(int _minute);
|
||||
void setHighestPeak(double _highest);
|
||||
void setArrowObjName(string _name);
|
||||
void setDistance(int _dist);
|
||||
void setDate(datetime _givenDate);
|
||||
|
||||
|
||||
// OTHER FUNCTIONS
|
||||
|
||||
double calculateFibPrice(double _fibLevel, double _lowPrice, double _highPrice); // calculate the fibonacci price based on the given level, and saves the price in the fibPrice88 variable in the object
|
||||
void updateDistance();
|
||||
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
LowFractal::LowFractal()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
LowFractal::LowFractal(double _price, int _leftPeriod, int _rightPeriod,datetime _date, ENUM_TIMEFRAMES _tf)
|
||||
{
|
||||
// the constructor sets the data to the attribues , and calculates the real time of the fractal , because the given minute and hour
|
||||
// are not the real time, they are the time of when the fractal was "known to be a fractal", which is after _righPeriod amount of candles
|
||||
|
||||
lowPrice = _price ;
|
||||
leftPeriod = _leftPeriod;
|
||||
rightPeriod = _rightPeriod;
|
||||
buyLimitPrice = -1 ;
|
||||
distance = _rightPeriod+1;
|
||||
arrowObjName = " " ;
|
||||
highestPeak = -1;
|
||||
|
||||
|
||||
date = iTime(_Symbol,_tf,_rightPeriod+1); // bring the actual date of the fractal
|
||||
TimeToStruct(date,dateStruct); // convert the actual date into a struct
|
||||
|
||||
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
LowFractal::~LowFractal()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
double LowFractal:: getPrice()
|
||||
{
|
||||
|
||||
return lowPrice ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int LowFractal:: getLeftPeriod()
|
||||
{
|
||||
|
||||
return leftPeriod ;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int LowFractal:: getRightPeriod()
|
||||
{
|
||||
|
||||
return rightPeriod ;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int LowFractal:: getHour()
|
||||
{
|
||||
|
||||
return dateStruct.hour ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int LowFractal:: getMinute()
|
||||
{
|
||||
return dateStruct.min ;
|
||||
}
|
||||
|
||||
|
||||
double LowFractal:: getHighestPeak(){
|
||||
|
||||
return highestPeak ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int LowFractal:: getDistance(){
|
||||
|
||||
return distance ;
|
||||
}
|
||||
|
||||
|
||||
string LowFractal:: getArrowObjName(){
|
||||
return arrowObjName ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
datetime LowFractal:: getDate(){
|
||||
|
||||
return date ;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void LowFractal:: setPrice(double _price)
|
||||
{
|
||||
lowPrice = _price ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void LowFractal:: setLeftPeriod(int _leftPeriod)
|
||||
{
|
||||
leftPeriod = _leftPeriod ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void LowFractal:: setRightPeriod(int _rightPeriod)
|
||||
{
|
||||
rightPeriod = _rightPeriod ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void LowFractal:: setHour(int _hour)
|
||||
{
|
||||
hour = _hour ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void LowFractal:: setMinute(int _minute)
|
||||
{
|
||||
minute = _minute ;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
void LowFractal:: setArrowObjName(string _name){
|
||||
arrowObjName = _name ;
|
||||
|
||||
}
|
||||
|
||||
void LowFractal:: setDistance(int _dist){
|
||||
distance = _dist ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double LowFractal:: calculateFibPrice(double _fibLevel, double _lowPrice, double _highPrice){
|
||||
|
||||
double difference = _highPrice - _lowPrice ;
|
||||
double retracement = _fibLevel * difference ;
|
||||
double _fibPrice = _highPrice - retracement ;
|
||||
fibPrice = _fibPrice ;
|
||||
return fibPrice;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LowFractal:: setHighestPeak(double _highest){
|
||||
|
||||
highestPeak = _highest ;
|
||||
|
||||
}
|
||||
|
||||
void LowFractal:: setDate(datetime _givenDate){
|
||||
date = _givenDate;
|
||||
TimeToStruct(date,dateStruct); // convert the actual date into a struct
|
||||
}
|
||||
|
||||
void LowFractal:: updateDistance(){
|
||||
|
||||
distance++ ;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| LowFractalContainer.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#include "LowFractal.mqh"
|
||||
#include <library_functions.mqh>
|
||||
#define SIZE 700
|
||||
|
||||
double input arrowDistanceLows ;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
class LowFractalContainer
|
||||
{
|
||||
private:
|
||||
LowFractal* lowFractals[SIZE];
|
||||
int freeIndex ;
|
||||
double range ;
|
||||
ENUM_TIMEFRAMES timeFrame ;
|
||||
public:
|
||||
LowFractalContainer(ENUM_TIMEFRAMES _timeFrame);
|
||||
~LowFractalContainer();
|
||||
|
||||
//GETTERS
|
||||
|
||||
LowFractal* getLowFractal(int _index) {return lowFractals[_index] ;} // returns the fractal using its index in the array
|
||||
int getFreeIndex() {return freeIndex ; }
|
||||
|
||||
//SETTERS
|
||||
void setRange(double _range) {range = _range ;}
|
||||
|
||||
// OTHER FUNCTIONS
|
||||
void addLowFractal(LowFractal* _lowFractal); // adds low fractal to the low fractals array
|
||||
void printLowFractals(); // prints all low fractals data
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
LowFractalContainer::LowFractalContainer(ENUM_TIMEFRAMES _timeFrame)
|
||||
{
|
||||
timeFrame = _timeFrame ;
|
||||
freeIndex = 0 ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
LowFractalContainer::~LowFractalContainer()
|
||||
{
|
||||
|
||||
for(int i=0; i<SIZE; i++) // free the lowFractals array
|
||||
{
|
||||
delete lowFractals[i] ;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
void LowFractalContainer:: addLowFractal(LowFractal* _lowFractal){
|
||||
|
||||
|
||||
if(freeIndex == SIZE) // in this case we are adding a new fractal but the array is full so we need to do the following
|
||||
{
|
||||
ObjectDelete(_Symbol,lowFractals[0].getArrowObjName()); // delete the object arrow of the deleted fractal
|
||||
|
||||
|
||||
ObjectCreate(_Symbol,_lowFractal.getArrowObjName(),OBJ_ARROW_UP,0,iTime(Symbol(),timeFrame,_lowFractal.getDistance()),iLow(Symbol(),timeFrame,_lowFractal.getDistance()) - arrowDistanceLows); // create the new object arrow of the new fractal
|
||||
ObjectSetInteger(0,_lowFractal.getArrowObjName(),OBJPROP_COLOR,clrWhite);
|
||||
delete lowFractals[0]; // free the memory allocated for the fractal in the first index (because we wanna remove it from the array)
|
||||
|
||||
|
||||
for(int i=0; i< SIZE-1 ; i++) // shift the array
|
||||
{
|
||||
|
||||
lowFractals[i] = lowFractals[i+1];
|
||||
}
|
||||
|
||||
lowFractals[freeIndex - 1] = _lowFractal ;
|
||||
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
if(freeIndex == 0) // case of the first fractal
|
||||
{
|
||||
|
||||
lowFractals[freeIndex] = _lowFractal ;
|
||||
freeIndex++;
|
||||
|
||||
ObjectCreate(_Symbol,_lowFractal.getArrowObjName(),OBJ_ARROW_UP,0,iTime(Symbol(),timeFrame,_lowFractal.getDistance()),iLow(Symbol(),timeFrame,_lowFractal.getDistance()) - arrowDistanceLows);
|
||||
ObjectSetInteger(0,_lowFractal.getArrowObjName(),OBJPROP_COLOR,clrWhite);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
lowFractals[freeIndex] = _lowFractal ;
|
||||
freeIndex++;
|
||||
ObjectCreate(_Symbol,_lowFractal.getArrowObjName(),OBJ_ARROW_UP,0,iTime(Symbol(),timeFrame,_lowFractal.getDistance()),iLow(Symbol(),timeFrame,_lowFractal.getDistance()) - arrowDistanceLows);
|
||||
ObjectSetInteger(0,_lowFractal.getArrowObjName(),OBJPROP_COLOR,clrWhite);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void LowFractalContainer:: printLowFractals()
|
||||
{
|
||||
|
||||
if(freeIndex > 0)
|
||||
{
|
||||
|
||||
for(int i=0 ; i<freeIndex ; i++)
|
||||
{
|
||||
|
||||
Print(" Fractal " + i + " Time: ", lowFractals[i].getHour() + ":" + lowFractals[i].getMinute()+ " Price: "
|
||||
+ lowFractals[i].getPrice() + " Distance: " + lowFractals[i].getDistance() );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,299 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| MarketObserver.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#include "Zone.mqh"
|
||||
#include "ZoneContainer.mqh"
|
||||
#include "LowFractal.mqh"
|
||||
#include "HighFractal.mqh"
|
||||
#include "LowFractalContainer.mqh"
|
||||
#include "HighFractalContainer.mqh"
|
||||
|
||||
|
||||
// ALGORITHM CLASSES INCLUDES
|
||||
|
||||
#include "NewCandleDetector.mqh"
|
||||
|
||||
|
||||
// LIVE FORMING FRACTALS HANDLER CLASS
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
class MarketObserver
|
||||
{
|
||||
// THIS CLASS HAS ACCESS TO ZONE CONTAINER, HOWEVER IT MUST NOT CHANGE IT IT ONLY READS FROM THE ZONECONTAINER CLASS
|
||||
private:
|
||||
/*NewCandleDetector* newCandleDetector_H4;
|
||||
NewCandleDetector* newCandleDetector_H1 ;
|
||||
NewCandleDetector* newCandleDetector_M30;
|
||||
NewCandleDetector* newCandleDetector_M1 ;*/
|
||||
ZoneContainer* zoneContainer ; // must not be changed from this class
|
||||
bool closestResistanceWaiting ;
|
||||
bool closestSupportWaiting ;
|
||||
public:
|
||||
MarketObserver(ZoneContainer* _zoneContainer);
|
||||
~MarketObserver();
|
||||
|
||||
string zoneReached();
|
||||
|
||||
Zone* getClosestResistanceZone() {return zoneContainer.getHigherPivotIndexZone();}
|
||||
Zone* getClosestSupportZone() {return zoneContainer.getLowerPivotIndexZone();}
|
||||
bool reachedClosestSupportZone();
|
||||
bool reachedClosestResistanceZone();
|
||||
|
||||
|
||||
bool bearishCandleClosedInsideClosestSupportZone(ENUM_TIMEFRAMES tf);
|
||||
bool bullishCandleClosedInsideClosestResistanceZone(ENUM_TIMEFRAMES tf);
|
||||
|
||||
bool candleClosedBelowClosestSupportZone(ENUM_TIMEFRAMES tf);
|
||||
bool candleClosedAboveClosestResistanceZone(ENUM_TIMEFRAMES tf);
|
||||
bool candleClosedAboveResistanceByIndex(int _index,ENUM_TIMEFRAMES tf); // the index is a specific zone from the zones container
|
||||
bool candleClosedBelowSupportByIndex(int _index,ENUM_TIMEFRAMES tf); // the index is a specific zone from the zones container
|
||||
|
||||
bool isClosestResistanceWaiting() {return closestResistanceWaiting;}
|
||||
bool isClosestSupportWaiting() {return closestSupportWaiting;}
|
||||
|
||||
void setClosestResistanceWaiting(bool _state) {closestResistanceWaiting = _state ;}
|
||||
void setClosestSupportWaiting(bool _state) {closestSupportWaiting = _state ;}
|
||||
|
||||
|
||||
string giveMarketReport();
|
||||
|
||||
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
MarketObserver::MarketObserver(ZoneContainer* _zoneContainer)
|
||||
{
|
||||
/*newCandleDetector_H4 = new NewCandleDetector("PERIOD_H4") ;
|
||||
newCandleDetector_H1 = new NewCandleDetector("PERIOD_H1");
|
||||
newCandleDetector_M30 = new NewCandleDetector("PERIOD_M30");
|
||||
newCandleDetector_M1 = new NewCandleDetector("PERIOD_M1");*/
|
||||
|
||||
zoneContainer = _zoneContainer ;
|
||||
closestResistanceWaiting = false ;
|
||||
closestSupportWaiting = false ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
MarketObserver::~MarketObserver()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
string MarketObserver:: zoneReached()
|
||||
{
|
||||
|
||||
|
||||
int currentResistanceZoneIndex = zoneContainer.getHighZonePivot();
|
||||
int currentSupportZoneIndex = zoneContainer.getLowZonePivot();
|
||||
|
||||
if(currentResistanceZoneIndex != -1 && currentSupportZoneIndex != -1)
|
||||
{
|
||||
|
||||
|
||||
if(SymbolInfoDouble(_Symbol, SYMBOL_ASK) >= zoneContainer.getZoneByIndex(currentResistanceZoneIndex).getLowerEdge())
|
||||
{
|
||||
|
||||
Print("Reached the current resistance zone !");
|
||||
return "TYPE_RESISTANCE" ;
|
||||
|
||||
}
|
||||
|
||||
if(SymbolInfoDouble(_Symbol, SYMBOL_ASK) <= zoneContainer.getZoneByIndex(currentSupportZoneIndex).getHigherEdge())
|
||||
{
|
||||
Print("Reached the current support zone !");
|
||||
return "TYPE_SUPPORT" ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return "" ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MarketObserver:: reachedClosestSupportZone()
|
||||
{
|
||||
|
||||
int currentSupportZoneIndex = zoneContainer.getLowZonePivot();
|
||||
|
||||
if(currentSupportZoneIndex != -1)
|
||||
{
|
||||
if(SymbolInfoDouble(_Symbol, SYMBOL_ASK) <= zoneContainer.getZoneByIndex(currentSupportZoneIndex).getHigherEdge())
|
||||
{
|
||||
return true ;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MarketObserver:: reachedClosestResistanceZone()
|
||||
{
|
||||
|
||||
int currentResistanceZoneIndex = zoneContainer.getHighZonePivot();
|
||||
|
||||
if(currentResistanceZoneIndex != -1)
|
||||
{
|
||||
|
||||
if(SymbolInfoDouble(_Symbol, SYMBOL_ASK) >= zoneContainer.getZoneByIndex(currentResistanceZoneIndex).getLowerEdge())
|
||||
{
|
||||
return true ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MarketObserver:: bullishCandleClosedInsideClosestResistanceZone(ENUM_TIMEFRAMES tf)
|
||||
{
|
||||
|
||||
double previousCandleClose = iClose(_Symbol,tf,1);
|
||||
double previousCandleOpen = iOpen(_Symbol,tf,1);
|
||||
|
||||
if(zoneContainer.getHighZonePivot() != -1) // means if there is a pivot zone
|
||||
{
|
||||
|
||||
if((previousCandleClose > previousCandleOpen) && (previousCandleClose > zoneContainer.getZoneByIndex(zoneContainer.getHighZonePivot()).getLowerEdge()) && (previousCandleClose < zoneContainer.getZoneByIndex(zoneContainer.getHighZonePivot()).getHigherEdge())) // means if previous the candle is bullish and closed inside the resistance zone
|
||||
{
|
||||
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MarketObserver:: bearishCandleClosedInsideClosestSupportZone(ENUM_TIMEFRAMES tf)
|
||||
{
|
||||
|
||||
double previousCandleClose = iClose(_Symbol,tf,1);
|
||||
double previousCandleOpen = iOpen(_Symbol,tf,1);
|
||||
|
||||
if(zoneContainer.getLowZonePivot() != -1)
|
||||
{
|
||||
if((previousCandleClose < previousCandleOpen) && (previousCandleClose < zoneContainer.getZoneByIndex(zoneContainer.getLowZonePivot()).getHigherEdge()) && (previousCandleClose > zoneContainer.getZoneByIndex(zoneContainer.getLowZonePivot()).getLowerEdge())) // means if previous the candle is breaish and closed inside the support zone
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
string MarketObserver:: giveMarketReport()
|
||||
{
|
||||
|
||||
|
||||
return " " ;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MarketObserver:: candleClosedBelowClosestSupportZone(ENUM_TIMEFRAMES tf)
|
||||
{
|
||||
|
||||
double previousCandleClose = iClose(_Symbol,tf,1);
|
||||
double previousCandleOpen = iOpen(_Symbol,tf,1);
|
||||
|
||||
|
||||
if(zoneContainer.getLowZonePivot() != -1)
|
||||
{
|
||||
if((previousCandleClose < zoneContainer.getZoneByIndex(zoneContainer.getLowZonePivot()).getLowerEdge())) // means if the previous candle closed below the support zone
|
||||
{
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MarketObserver:: candleClosedAboveClosestResistanceZone(ENUM_TIMEFRAMES tf)
|
||||
{
|
||||
|
||||
double previousCandleClose = iClose(_Symbol,tf,1);
|
||||
double previousCandleOpen = iOpen(_Symbol,tf,1);
|
||||
|
||||
if(zoneContainer.getHighZonePivot() != -1) // means if there is a pivot zone
|
||||
{
|
||||
|
||||
if((previousCandleClose > zoneContainer.getZoneByIndex(zoneContainer.getHighZonePivot()).getHigherEdge())) // means if previous the candle closed above the resistance zone
|
||||
{
|
||||
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool MarketObserver:: candleClosedAboveResistanceByIndex(int _index,ENUM_TIMEFRAMES tf){
|
||||
|
||||
double previousCandleClose = iClose(_Symbol,tf,1);
|
||||
|
||||
if((previousCandleClose > zoneContainer.getZoneByIndex(_index).getHigherEdge())){
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,105 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| MarketObserverTiger.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
//+------------------------------------------------------------------+
|
||||
//| defines |
|
||||
//+------------------------------------------------------------------+
|
||||
// #define MacrosHello "Hello, world!"
|
||||
// #define MacrosYear 2010
|
||||
//+------------------------------------------------------------------+
|
||||
//| DLL imports |
|
||||
//+------------------------------------------------------------------+
|
||||
// #import "user32.dll"
|
||||
// int SendMessageA(int hWnd,int Msg,int wParam,int lParam);
|
||||
// #import "my_expert.dll"
|
||||
// int ExpertRecalculate(int wParam,int lParam);
|
||||
// #import
|
||||
//+------------------------------------------------------------------+
|
||||
//| EX5 imports |
|
||||
//+------------------------------------------------------------------+
|
||||
// #import "stdlib.ex5"
|
||||
// string ErrorDescription(int error_code);
|
||||
// #import
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Zone.mqh"
|
||||
#include "ZoneContainer.mqh"
|
||||
|
||||
|
||||
// ALGORITHM CLASSES INCLUDES
|
||||
|
||||
#include "NewCandleDetector.mqh"
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
class MarketObserverTiger
|
||||
{
|
||||
// THIS CLASS HAS ACCESS TO ZONE CONTAINER, HOWEVER IT MUST NOT CHANGE IT IT ONLY READS FROM THE ZONECONTAINER CLASS
|
||||
private:
|
||||
|
||||
|
||||
|
||||
public:
|
||||
MarketObserverTiger();
|
||||
~MarketObserverTiger();
|
||||
|
||||
string zoneReached();
|
||||
bool candleClosedAboveResistanceByIndex(int _index,ENUM_TIMEFRAMES tf,ZoneContainer& resistanceZoneContainer); // the index is a specific zone from the zones container
|
||||
bool candleClosedBelowSupportByIndex(int _index,ENUM_TIMEFRAMES tf,ZoneContainer& supportZoneContainer); // the index is a specific zone from the zones container
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
MarketObserverTiger::MarketObserverTiger()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
MarketObserverTiger::~MarketObserverTiger()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MarketObserverTiger:: candleClosedAboveResistanceByIndex(int _index,ENUM_TIMEFRAMES tf,ZoneContainer& resistanceZoneContainer)
|
||||
{
|
||||
|
||||
double previousCandleClose = iClose(_Symbol,tf,1);
|
||||
|
||||
if((previousCandleClose > resistanceZoneContainer.getZoneByIndex(_index).getHigherEdge()))
|
||||
{
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool MarketObserverTiger:: candleClosedBelowSupportByIndex(int _index, ENUM_TIMEFRAMES tf, ZoneContainer& supportZoneContainer){
|
||||
|
||||
|
||||
double previousCandleClose = iClose(_Symbol,tf,1);
|
||||
if(previousCandleClose < supportZoneContainer.getZoneByIndex(_index).getLowerEdge()){
|
||||
return true ;
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
@@ -0,0 +1,378 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| NewCandleDetector.mqh |
|
||||
//| Copyright 2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
class NewCandleDetector
|
||||
{
|
||||
private:
|
||||
string timeFrame ;
|
||||
datetime beginDate ; // this datetime gets initialized only after the first call of the isNewCandle() function
|
||||
MqlDateTime currTimeStruct;
|
||||
MqlDateTime beginDateStruct;
|
||||
bool firstCallHappened;
|
||||
public:
|
||||
NewCandleDetector(string _timeFrame);
|
||||
|
||||
~NewCandleDetector();
|
||||
|
||||
// GETTERS
|
||||
datetime getBeginDate() {return beginDate;}
|
||||
|
||||
void setTimeFrame(string _timeFrame) {timeFrame = _timeFrame;}
|
||||
bool isNewCandle();
|
||||
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
NewCandleDetector::NewCandleDetector(string _timeFrame)
|
||||
{
|
||||
|
||||
timeFrame = _timeFrame ;
|
||||
firstCallHappened = false;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
NewCandleDetector::~NewCandleDetector()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool NewCandleDetector:: isNewCandle()
|
||||
{
|
||||
|
||||
|
||||
|
||||
if(timeFrame == "PERIOD_M1")
|
||||
{
|
||||
|
||||
if(firstCallHappened == false)
|
||||
{
|
||||
|
||||
beginDate = iTime(_Symbol,PERIOD_M1,0);
|
||||
firstCallHappened = true;
|
||||
}
|
||||
|
||||
if(firstCallHappened == true)
|
||||
{
|
||||
datetime currTime = iTime(_Symbol,PERIOD_M1,0);
|
||||
TimeToStruct(beginDate,beginDateStruct);
|
||||
TimeToStruct(currTime,currTimeStruct);
|
||||
|
||||
if(beginDateStruct.min == currTimeStruct.min)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Print("in a new candle !, asset: " + _Symbol);
|
||||
beginDate = currTime;
|
||||
return true ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_M2")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
if(timeFrame == "PERIOD_M3")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_M4")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_M5")
|
||||
{
|
||||
|
||||
if(firstCallHappened == false)
|
||||
{
|
||||
beginDate = iTime(_Symbol,PERIOD_M5,0);
|
||||
firstCallHappened = true;
|
||||
}
|
||||
|
||||
if(firstCallHappened == true)
|
||||
{
|
||||
datetime currTime = iTime(_Symbol,PERIOD_M5,0);
|
||||
TimeToStruct(beginDate,beginDateStruct);
|
||||
TimeToStruct(currTime,currTimeStruct);
|
||||
|
||||
if(beginDateStruct.min == currTimeStruct.min)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("in a new candle !, asset: " + _Symbol);
|
||||
beginDate = currTime;
|
||||
return true ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_M6")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_M10")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_M12")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_M15")
|
||||
{
|
||||
|
||||
if(firstCallHappened == false)
|
||||
{
|
||||
beginDate = iTime(_Symbol,PERIOD_M15,0);
|
||||
firstCallHappened = true;
|
||||
}
|
||||
|
||||
if(firstCallHappened == true)
|
||||
{
|
||||
datetime currTime = iTime(_Symbol,PERIOD_M15,0);
|
||||
TimeToStruct(beginDate,beginDateStruct);
|
||||
TimeToStruct(currTime,currTimeStruct);
|
||||
|
||||
if(beginDateStruct.min == currTimeStruct.min)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
beginDate = currTime;
|
||||
return true ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_M20")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_M30")
|
||||
{
|
||||
if(firstCallHappened == false)
|
||||
{
|
||||
beginDate = iTime(_Symbol,PERIOD_M30,0);
|
||||
firstCallHappened = true;
|
||||
}
|
||||
|
||||
if(firstCallHappened == true)
|
||||
{
|
||||
datetime currTime = iTime(_Symbol,PERIOD_M30,0);
|
||||
TimeToStruct(beginDate,beginDateStruct);
|
||||
TimeToStruct(currTime,currTimeStruct);
|
||||
|
||||
if(beginDateStruct.min == currTimeStruct.min)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
beginDate = currTime;
|
||||
return true ;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_H1")
|
||||
{
|
||||
if(firstCallHappened == false)
|
||||
{
|
||||
beginDate = iTime(_Symbol,PERIOD_H1,0);
|
||||
firstCallHappened = true;
|
||||
}
|
||||
|
||||
if(firstCallHappened == true)
|
||||
{
|
||||
datetime currTime = iTime(_Symbol,PERIOD_H1,0);
|
||||
TimeToStruct(beginDate,beginDateStruct);
|
||||
TimeToStruct(currTime,currTimeStruct);
|
||||
|
||||
if(beginDateStruct.hour == currTimeStruct.hour)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
beginDate = currTime;
|
||||
return true ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_H2")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_H3")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_H4")
|
||||
{
|
||||
if(firstCallHappened == false)
|
||||
{
|
||||
beginDate = iTime(_Symbol,PERIOD_H4,0);
|
||||
firstCallHappened = true;
|
||||
}
|
||||
|
||||
if(firstCallHappened == true)
|
||||
{
|
||||
datetime currTime = iTime(_Symbol,PERIOD_H4,0);
|
||||
TimeToStruct(beginDate,beginDateStruct);
|
||||
TimeToStruct(currTime,currTimeStruct);
|
||||
|
||||
if(beginDateStruct.hour == currTimeStruct.hour)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
beginDate = currTime;
|
||||
return true ;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_H6")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_H8")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_H12")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_D1")
|
||||
{
|
||||
|
||||
if(firstCallHappened == false)
|
||||
{
|
||||
beginDate = iTime(_Symbol,PERIOD_D1,0);
|
||||
firstCallHappened = true;
|
||||
}
|
||||
|
||||
if(firstCallHappened == true)
|
||||
{
|
||||
datetime currTime = iTime(_Symbol,PERIOD_D1,0);
|
||||
TimeToStruct(beginDate,beginDateStruct);
|
||||
TimeToStruct(currTime,currTimeStruct);
|
||||
|
||||
if(beginDateStruct.day == currTimeStruct.day)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
beginDate = currTime;
|
||||
return true ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_W1")
|
||||
{
|
||||
|
||||
|
||||
if(firstCallHappened == false)
|
||||
{
|
||||
beginDate = iTime(_Symbol,PERIOD_W1,0);
|
||||
firstCallHappened = true;
|
||||
}
|
||||
|
||||
if(firstCallHappened == true)
|
||||
{
|
||||
datetime currTime = iTime(_Symbol,PERIOD_W1,0);
|
||||
TimeToStruct(beginDate,beginDateStruct);
|
||||
TimeToStruct(currTime,currTimeStruct);
|
||||
|
||||
if(beginDateStruct.day == currTimeStruct.day)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
beginDate = currTime;
|
||||
return true ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
if(timeFrame == "PERIOD_MN1")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user