695 lines
53 KiB
Plaintext
695 lines
53 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| ORDER BLOCKS EA.mq5 |
|
|
//| Copyright 2024, ALLAN MUNENE MUTIIRIA. #@Forex Algo-Trader. |
|
|
//| https://youtube.com/@ForexAlgo-Trader? |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2024, ALLAN MUNENE MUTIIRIA. #@Forex Algo-Trader"
|
|
#property link "https://youtube.com/@ForexAlgo-Trader?"
|
|
#property description "======= IMPORTANT =======\n"
|
|
#property description "1. This is a FREE EA."
|
|
#property description "2. To get the source code of the EA, follow the Copyright link."
|
|
#property description "3. Incase of anything, contact developer via the link provided."
|
|
"Hope you will enjoy the EA Logic.\n"
|
|
#property description "*** HAPPY TRADING! ***"
|
|
#property version "2.00"
|
|
|
|
sinput group "✔🔰 EA GENERAL SETTINGS 💱💲"
|
|
input double inpLot = 0.01; // Lotsize
|
|
input ulong magic_no = 1234567; // Magic Number
|
|
input int sl_tp_pts = 300; // Stop Loss/Take Profit Points
|
|
input double r2r_ratio = 7; // Risk : Reward Ratio
|
|
sinput string ob_up_name = "Bullish Order Block"; // OB Up Name
|
|
sinput string ob_down_name = "Bearish Order Block"; // OB Down Name
|
|
sinput short ob_up_unicode = 0x2BED; // OB Up Unicode
|
|
sinput short ob_down_unicode = 0x2BEF; // OB Down Unicode
|
|
sinput string range_name = "Range"; // Range name
|
|
|
|
sinput string src_code1 = "https://t.me/forexalgo_trading"; // Source Code HERE 👉
|
|
sinput string src_code2 = "https://youtube.com/@ForexAlgo-Trader?"; // Join Community HERE 👉
|
|
|
|
input int range_candles = 7; // Range Candles
|
|
input double max_deviation = 50; // Maximum Deviation Points
|
|
input int starting_index = 1; // Starting Index
|
|
input int wait_bars = 3; // Validation Wait Bars
|
|
|
|
sinput color def_clr_up = clrLime; // Bullish OB Color
|
|
sinput color def_clr_down = clrRed; // Bearish OB Color
|
|
sinput color def_invalid = clrBlue; // Invalid OB Color
|
|
sinput color def_text = clrBlack; // Text Color
|
|
sinput bool prt = false; // Print Statements
|
|
sinput int fontSize = 15; // Font Size
|
|
|
|
|
|
|
|
#include <Trade/Trade.mqh>
|
|
CTrade obj_Trade;
|
|
|
|
struct PriceIndex{
|
|
double price;
|
|
int index;
|
|
};
|
|
|
|
PriceIndex highestHigh = {0,0};
|
|
PriceIndex lowestLow = {0,0};
|
|
bool breakoutDetected = false;
|
|
|
|
double impulseLow = 0.0;
|
|
double impulseHigh = 0.0;
|
|
int breakoutBarIndex = -1;
|
|
datetime breakoutTime = 0;
|
|
|
|
string totalOBs_names[];
|
|
datetime totalOBs_dates[];
|
|
bool totalOBs_is_signals[];
|
|
|
|
bool is_OB_UP = false;
|
|
bool is_OB_DOWN = false;
|
|
|
|
#define OB_Prefix "OB REC "
|
|
#define CLR_UP def_clr_up
|
|
#define CLR_DOWN def_clr_down
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit(){
|
|
//---
|
|
obj_Trade.SetExpertMagicNumber(magic_no);
|
|
if (prt){
|
|
Print("Success. "+__FILE__+" Initialized...");
|
|
}
|
|
//---
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason){
|
|
//---
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert tick function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick(){
|
|
//---
|
|
static bool isNewBar = false;
|
|
int currBars = iBars(_Symbol,_Period);
|
|
static int prevBars = currBars;
|
|
|
|
if (prevBars == currBars){isNewBar = false;}
|
|
else if (prevBars != currBars){
|
|
isNewBar = true;
|
|
prevBars = currBars;
|
|
}
|
|
|
|
if (!isNewBar)
|
|
return;
|
|
|
|
int rangeCandles = range_candles;
|
|
double maxDeviation = max_deviation;
|
|
int startingIndex = starting_index;
|
|
int waitBars = wait_bars;
|
|
|
|
if (!breakoutDetected){
|
|
if (highestHigh.price == 0 && lowestLow.price == 0){
|
|
if (IsConsolidationEqualHighsAndLows(rangeCandles,maxDeviation,startingIndex)){
|
|
GetHighestHigh(rangeCandles,startingIndex,highestHigh);
|
|
GetLowestLow(rangeCandles,startingIndex,lowestLow);
|
|
|
|
if (prt){
|
|
Print("Consolidation range established: Highest High = ",highestHigh.price,
|
|
" at index ,",highestHigh.index,
|
|
" and Lowest Low = ",lowestLow.price,
|
|
" at index ",lowestLow.index
|
|
);
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
ExtendRangeIfWithinLimits();
|
|
}
|
|
}
|
|
|
|
if (highestHigh.price > 0 && lowestLow.price > 0){
|
|
breakoutDetected = CheckRangeBreak(highestHigh,lowestLow);
|
|
}
|
|
|
|
if (breakoutDetected){
|
|
if (prt){
|
|
Print("Breakout detected. Resetting for the next range.");
|
|
}
|
|
|
|
breakoutBarIndex = 1;
|
|
breakoutTime = TimeCurrent();
|
|
impulseHigh = highestHigh.price;
|
|
impulseLow = lowestLow.price;
|
|
|
|
breakoutDetected = false;
|
|
highestHigh.price = 0;
|
|
highestHigh.index = 0;
|
|
|
|
lowestLow.price = 0;
|
|
lowestLow.index = 0;
|
|
}
|
|
|
|
if (breakoutBarIndex >= 0 && TimeCurrent() > breakoutTime+waitBars*PeriodSeconds()){
|
|
DetectImpulsiveMovement(impulseHigh,impulseLow,waitBars,1);
|
|
|
|
bool is_OB_Valid = is_OB_UP || is_OB_DOWN;
|
|
|
|
datetime time1 = iTime(_Symbol,_Period,rangeCandles+waitBars+1);
|
|
double price1 = impulseHigh;
|
|
|
|
int visisbleBars = (int)ChartGetInteger(0,CHART_VISIBLE_BARS);
|
|
datetime time2 = is_OB_Valid ? time1+(visisbleBars/1)*PeriodSeconds() : time(waitBars+1);
|
|
double price2 = impulseLow;
|
|
|
|
string obName = OB_Prefix+"("+TimeToString(time1)+")";
|
|
color obClr = clrBlack;
|
|
|
|
if (is_OB_Valid){obClr = is_OB_UP ? CLR_UP : CLR_DOWN;}
|
|
else if (!is_OB_Valid){obClr = def_invalid;}
|
|
|
|
string obText = "";
|
|
|
|
if (is_OB_Valid){obText = is_OB_UP ? ob_up_name+ShortToString(ob_up_unicode) : ob_down_name+ShortToString(ob_down_unicode);}
|
|
else if (!is_OB_Valid){obText = range_name;}
|
|
|
|
if (!is_OB_Valid){
|
|
if (ObjectFind(0,obName) < 0){
|
|
CreateRec(obName,time1,price1,time2,price2,obClr,obText);
|
|
}
|
|
}
|
|
else if (is_OB_Valid){
|
|
if (ObjectFind(0,obName) < 0){
|
|
CreateRec(obName,time1,price1,time2,price2,obClr,obText);
|
|
|
|
if (prt){Print("Old Arraysize = ",ArraySize(totalOBs_names));}
|
|
ArrayResize(totalOBs_names,ArraySize(totalOBs_names)+1);
|
|
if (prt){Print("New Arraysize = ",ArraySize(totalOBs_names));}
|
|
totalOBs_names[ArraySize(totalOBs_names)-1] = obName;
|
|
if (prt){ArrayPrint(totalOBs_names);}
|
|
|
|
if (prt){Print("Old Arraysize = ",ArraySize(totalOBs_dates));}
|
|
ArrayResize(totalOBs_dates,ArraySize(totalOBs_dates)+1);
|
|
if (prt){Print("New Arraysize = ",ArraySize(totalOBs_dates));}
|
|
totalOBs_dates[ArraySize(totalOBs_dates)-1] = time2;
|
|
if (prt){ArrayPrint(totalOBs_dates);}
|
|
|
|
if (prt){Print("Old Arraysize = ",ArraySize(totalOBs_is_signals));}
|
|
ArrayResize(totalOBs_is_signals,ArraySize(totalOBs_is_signals)+1);
|
|
if (prt){Print("New Arraysize = ",ArraySize(totalOBs_is_signals));}
|
|
totalOBs_is_signals[ArraySize(totalOBs_is_signals)-1] = false;
|
|
if (prt){ArrayPrint(totalOBs_is_signals);}
|
|
}
|
|
}
|
|
|
|
breakoutBarIndex = -1;
|
|
breakoutTime = 0;
|
|
impulseHigh = 0;
|
|
impulseLow = 0;
|
|
is_OB_UP = false;
|
|
is_OB_DOWN = false;
|
|
}
|
|
|
|
for (int j=ArraySize(totalOBs_names)-1; j>=0; j--){
|
|
string obNAME = totalOBs_names[j];
|
|
bool obExist = false;
|
|
|
|
double obHigh = ObjectGetDouble(0,obNAME,OBJPROP_PRICE,0);
|
|
double obLow = ObjectGetDouble(0,obNAME,OBJPROP_PRICE,1);
|
|
datetime objTime1 = (datetime)ObjectGetInteger(0,obNAME,OBJPROP_TIME,0);
|
|
datetime objTime2 = (datetime)ObjectGetInteger(0,obNAME,OBJPROP_TIME,1);
|
|
color obColor = (color)ObjectGetInteger(0,obNAME,OBJPROP_COLOR);
|
|
|
|
if (time(1) < objTime2){
|
|
obExist = true;
|
|
}
|
|
|
|
double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
|
|
double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
|
|
|
|
if (obColor == CLR_UP && Ask > obHigh && close(1) > obHigh && open(1) < obHigh && !totalOBs_is_signals[j]){
|
|
if (prt){Print("BUY SIGNAL for (",obNAME,") Now @ ",Ask);}
|
|
double sl = Bid-(sl_tp_pts*r2r_ratio)*_Point;
|
|
double tp = Bid+sl_tp_pts*_Point;
|
|
|
|
double trade_lots = Check1_ValidateVolume_Lots(inpLot);
|
|
|
|
if (Check2_Margin(ORDER_TYPE_BUY,trade_lots) &&
|
|
Check3_VolumeLimit(trade_lots) &&
|
|
Check4_TradeLevels(POSITION_TYPE_BUY,sl,tp)
|
|
){
|
|
obj_Trade.Buy(trade_lots,_Symbol,Ask,sl,tp);
|
|
totalOBs_is_signals[j] = true;
|
|
if (prt){ArrayPrint(totalOBs_names,_Digits," [< >] ");}
|
|
if (prt){ArrayPrint(totalOBs_is_signals,_Digits," [< >] ");}
|
|
}
|
|
|
|
}
|
|
else if (obColor == CLR_DOWN && Bid < obLow && close(1) < obLow && open(1) > obLow && !totalOBs_is_signals[j]){
|
|
if (prt){Print("SELL SIGNAL for (",obNAME,") Now @ ",Bid);}
|
|
double sl = Ask+(sl_tp_pts*r2r_ratio)*_Point;
|
|
double tp = Ask-sl_tp_pts*_Point;
|
|
|
|
double trade_lots = Check1_ValidateVolume_Lots(inpLot);
|
|
|
|
if (Check2_Margin(ORDER_TYPE_SELL,trade_lots) &&
|
|
Check3_VolumeLimit(trade_lots) &&
|
|
Check4_TradeLevels(POSITION_TYPE_SELL,sl,tp)
|
|
){
|
|
obj_Trade.Sell(trade_lots,_Symbol,Bid,sl,tp);
|
|
totalOBs_is_signals[j] = true;
|
|
if (prt){ArrayPrint(totalOBs_names,_Digits," [< >] ");}
|
|
if (prt){ArrayPrint(totalOBs_is_signals,_Digits," [< >] ");}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if (obExist == false){
|
|
bool removeName = ArrayRemove(totalOBs_names,0,1);
|
|
bool removeTime = ArrayRemove(totalOBs_dates,0,1);
|
|
bool remove_isSignal = ArrayRemove(totalOBs_is_signals,0,1);
|
|
|
|
if (removeName && removeTime && remove_isSignal){
|
|
if (prt){
|
|
Print("Success removing the OB DATA from the arrays. New data is as below:");
|
|
Print("Total sizes => OBs: ",ArraySize(totalOBs_names),", TIMEs: ",ArraySize(totalOBs_dates),", SIGNALs: ",ArraySize(totalOBs_is_signals));
|
|
ArrayPrint(totalOBs_names);
|
|
ArrayPrint(totalOBs_dates);
|
|
ArrayPrint(totalOBs_is_signals);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
bool IsConsolidationEqualHighsAndLows(int rangeCandles, double maxDeviation, int startingIndex){
|
|
|
|
for (int i=startingIndex; i<startingIndex+rangeCandles-1; i++){
|
|
if (MathAbs(high(i) - high(i+1)) > maxDeviation*Point()){
|
|
return false;
|
|
}
|
|
if (MathAbs(low(i) - low(i+1)) > maxDeviation*Point()){
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void GetHighestHigh(int rangeCandles, int startingIndex, PriceIndex &highestHighRef){
|
|
highestHighRef.price = high(startingIndex);
|
|
highestHighRef.index = startingIndex;
|
|
|
|
for (int i=startingIndex+1; i<startingIndex+rangeCandles; i++){
|
|
if (high(i) > highestHighRef.price){
|
|
highestHighRef.price = high(i);
|
|
highestHighRef.index = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
void GetLowestLow(int rangeCandles, int startingIndex, PriceIndex &lowestLowRef){
|
|
lowestLowRef.price = low(startingIndex);
|
|
lowestLowRef.index = startingIndex;
|
|
|
|
for (int i=startingIndex+1; i<startingIndex+rangeCandles; i++){
|
|
if (low(i) < lowestLowRef.price){
|
|
lowestLowRef.price = low(i);
|
|
lowestLowRef.index = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ExtendRangeIfWithinLimits(){
|
|
double currentHigh = high(1);
|
|
double currentLow = low(1);
|
|
|
|
if (currentHigh <= highestHigh.price && currentLow >= lowestLow.price){
|
|
if (prt){
|
|
Print("Range extended: Including candle with high = ",currentHigh," and low = ",currentLow);
|
|
}
|
|
}
|
|
else {
|
|
if (prt){
|
|
Print("No extension posiible. The current bar is outside the range.");
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CheckRangeBreak(PriceIndex &highestHighRef, PriceIndex &lowestLowRef){
|
|
double closingPrice = close(1);
|
|
|
|
if (closingPrice > highestHighRef.price){
|
|
if (prt){
|
|
Print("Range break upwards detected. Closing price ",closingPrice," is above the highest high: ",highestHighRef.price);
|
|
}
|
|
return true;
|
|
}
|
|
else if (closingPrice < lowestLowRef.price){
|
|
if (prt){
|
|
Print("Range break downwards detected. Closing price ",closingPrice," is below the lowest low: ",lowestLowRef.price);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void DetectImpulsiveMovement(double breakoutHigh,double breakoutLow,int impulseBars,double impulseThreshold){
|
|
double range = breakoutHigh - breakoutLow;
|
|
double impulseThresholdPrice = range *impulseThreshold;
|
|
|
|
for (int i=1; i<=impulseBars; i++){
|
|
double closePrice = close(i);
|
|
if (closePrice >= breakoutHigh+impulseThresholdPrice){
|
|
is_OB_UP = true;
|
|
if (prt){
|
|
Print("Impulsive upward movement detected: Close Price = ",closePrice,
|
|
", Threshold = ",breakoutHigh+impulseThresholdPrice
|
|
);
|
|
}
|
|
return;
|
|
}
|
|
else if (closePrice <= breakoutLow-impulseThresholdPrice){
|
|
is_OB_DOWN = true;
|
|
if (prt){
|
|
Print("Impulsive downward movement detected: Close Price = ",closePrice,
|
|
", Threshold = ",breakoutHigh-impulseThresholdPrice
|
|
);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
is_OB_UP = false;
|
|
is_OB_DOWN = false;
|
|
if (prt){Print("No impulsive movement detected after breakout.");}
|
|
}
|
|
|
|
|
|
double high(int index){return iHigh(_Symbol,_Period,index);}
|
|
double low(int index){return iLow(_Symbol,_Period,index);}
|
|
double open(int index){return iOpen(_Symbol,_Period,index);}
|
|
double close(int index){return iClose(_Symbol,_Period,index);}
|
|
datetime time(int index){return iTime(_Symbol,_Period,index);}
|
|
|
|
void CreateRec(string objName,datetime time1,double price1,
|
|
datetime time2,double price2,color clr,string txt
|
|
){
|
|
if (ObjectFind(0,objName) < 0){
|
|
ObjectCreate(0,objName,OBJ_RECTANGLE,0,time1,price1,time2,price2);
|
|
if (prt){
|
|
Print("SUCCESS CREATING OBJECT >",objName,"< WITH"," T1: ",time1,", P1: ",price1,
|
|
", T2: ",time2,", P2: ",price2);
|
|
}
|
|
ObjectSetInteger(0,objName,OBJPROP_TIME,0,time1);
|
|
ObjectSetDouble(0,objName,OBJPROP_PRICE,0,price1);
|
|
ObjectSetInteger(0,objName,OBJPROP_TIME,1,time2);
|
|
ObjectSetDouble(0,objName,OBJPROP_PRICE,1,price2);
|
|
ObjectSetInteger(0,objName,OBJPROP_FILL,true);
|
|
ObjectSetInteger(0,objName,OBJPROP_COLOR,clr);
|
|
ObjectSetInteger(0,objName,OBJPROP_BACK,false);
|
|
|
|
string description_txt = txt;
|
|
string textObjName = objName+description_txt;
|
|
|
|
datetime midTime = time1 +(time2-time1)/2;
|
|
double midPrice = (price1+price2)/2;
|
|
|
|
if (ObjectFind(0,textObjName) < 0){
|
|
ObjectCreate(0,textObjName,OBJ_TEXT,0,midTime,midPrice);
|
|
ObjectSetString(0,textObjName,OBJPROP_TEXT,description_txt);
|
|
ObjectSetInteger(0,textObjName,OBJPROP_COLOR,def_text);
|
|
ObjectSetInteger(0,textObjName,OBJPROP_FONTSIZE,fontSize);
|
|
ObjectSetInteger(0,textObjName,OBJPROP_ANCHOR,ANCHOR_CENTER);
|
|
if (prt){
|
|
Print("SUCCESS CREATING LABEL >",textObjName,"< WITH TEXT: ",description_txt);
|
|
}
|
|
}
|
|
|
|
ChartRedraw(0);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 1. CHECK TRADING VOLUME |
|
|
//+------------------------------------------------------------------+
|
|
|
|
double Check1_ValidateVolume_Lots(double lots){
|
|
double symbolVol_Min = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
|
|
double symbolVol_Max = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
|
|
double symbolVol_STEP = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
|
|
|
|
double accepted_Lots;
|
|
double CurrentLots = lots;
|
|
accepted_Lots = MathMax(MathMin(CurrentLots,symbolVol_Max),symbolVol_Min);
|
|
|
|
int lotDigits = 0;
|
|
if (symbolVol_Min == 1) lotDigits = 0;
|
|
if (symbolVol_Min == 0.1) lotDigits = 1;
|
|
if (symbolVol_Min == 0.01) lotDigits = 2;
|
|
if (symbolVol_Min == 0.001) lotDigits = 3;
|
|
|
|
double normalized_lots = NormalizeDouble(accepted_Lots,lotDigits);
|
|
//Print("MIN LOTS = ",symbolVol_Min,", NORMALIZED LOTS = ",normalized_lots);
|
|
|
|
return (normalized_lots);
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 2. CHECK MONEY/MARGIN TO OPEN POSITION |
|
|
//+------------------------------------------------------------------+
|
|
|
|
bool Check2_Margin(ENUM_ORDER_TYPE Order_Type,double lot_Vol){
|
|
double margin;
|
|
double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
|
|
double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
|
|
|
|
double openPrice = (Order_Type == ORDER_TYPE_BUY) ? Ask : Bid;
|
|
|
|
bool result = OrderCalcMargin(Order_Type,_Symbol,lot_Vol,openPrice,margin);
|
|
if (result == false){
|
|
ResetLastError();
|
|
Print("ERROR: Something Unexpected Happened While Calculating Margin\n",
|
|
"RESULT = ",result,", ERROR = ",_LastError);
|
|
return (false);
|
|
}
|
|
if (margin > AccountInfoDouble(ACCOUNT_MARGIN_FREE)){
|
|
Print("WARNING! NOT ENOUGH MARGIN TO OPEN THE POSITION. NEEDED = ",margin);
|
|
return (false);
|
|
}
|
|
return (true);
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 3. CHECK VOLUME LIMIT |
|
|
//+------------------------------------------------------------------+
|
|
|
|
bool Check3_VolumeLimit(double lots_Vol_Limit){
|
|
double volumeLimit = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_LIMIT);
|
|
double symb_Vol_Max40 = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
|
|
double allowed_Vol_Lim = (volumeLimit == 0) ? symb_Vol_Max40 : volumeLimit;
|
|
if (getAllVolume()+lots_Vol_Limit > allowed_Vol_Lim){
|
|
Print("WARNING! VOLUME LIMIT REACHED: LIMIT = ",allowed_Vol_Lim);
|
|
return (false);
|
|
}
|
|
return (true);
|
|
}
|
|
|
|
double getAllVolume(){
|
|
ulong ticket=0;
|
|
double Volume=0;
|
|
|
|
for (int i=PositionsTotal()-1 ;i>=0 ;i--){
|
|
ticket = PositionGetTicket(i);
|
|
if (PositionSelectByTicket(ticket)){
|
|
if (PositionGetString(POSITION_SYMBOL)==_Symbol){
|
|
Volume += PositionGetDouble(POSITION_VOLUME);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i=OrdersTotal()-1 ;i>=0 ;i--){
|
|
ticket = OrderGetTicket(i);
|
|
if (OrderSelect(ticket)){
|
|
if (OrderGetString(ORDER_SYMBOL)==_Symbol){
|
|
Volume += OrderGetDouble(ORDER_VOLUME_CURRENT);
|
|
}
|
|
}
|
|
}
|
|
return (Volume);
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 4. CHECK TRADE LEVELS |
|
|
//+------------------------------------------------------------------+
|
|
|
|
bool Check4_TradeLevels(ENUM_POSITION_TYPE pos_Type,double sl=0,double tp=0,ulong tkt=0){
|
|
double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
|
|
double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
|
|
|
|
int stopLevel = (int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL);
|
|
int freezeLevel = (int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_FREEZE_LEVEL);
|
|
int spread = (int)SymbolInfoInteger(_Symbol,SYMBOL_SPREAD);
|
|
|
|
double stopLevel_Pts = stopLevel*_Point;
|
|
double freezeLevel_Pts = freezeLevel*_Point;
|
|
|
|
if (pos_Type == POSITION_TYPE_BUY){
|
|
// STOP LEVELS CHECK
|
|
if (tp > 0 && tp - Bid < stopLevel_Pts){
|
|
Print("WARNING! BUY TP ",tp,", Bid ",Bid," (TP-Bid = ",NormalizeDouble((tp-Bid)/_Point,_Digits),") WITHIN STOP LEVEL OF ",stopLevel);
|
|
return (false);
|
|
}
|
|
if (sl > 0 && Bid - sl < stopLevel_Pts){
|
|
Print("WARNING! BUY SL ",sl,", Bid ",Bid," (Bid-SL = ",NormalizeDouble((Bid-sl)/_Point,_Digits),") WITHIN STOP LEVEL OF ",stopLevel);
|
|
return (false);
|
|
}
|
|
// FREEZE LEVELS CHECK
|
|
if (tp > 0 && tp - Bid < freezeLevel_Pts){
|
|
Print("WARNING! BUY TP ",tp,", Bid ",Bid," (TP-Bid = ",NormalizeDouble((tp-Bid)/_Point,_Digits),") WITHIN FREEZE LEVEL OF ",freezeLevel);
|
|
return (false);
|
|
}
|
|
if (sl > 0 && Bid - sl < freezeLevel_Pts){
|
|
Print("WARNING! BUY SL ",sl,", Bid ",Bid," (Bid-SL = ",NormalizeDouble((Bid-sl)/_Point,_Digits),") WITHIN FREEZE LEVEL OF ",freezeLevel);
|
|
return (false);
|
|
}
|
|
}
|
|
if (pos_Type == POSITION_TYPE_SELL){
|
|
// STOP LEVELS CHECK
|
|
if (tp > 0 && Ask - tp < stopLevel_Pts){
|
|
Print("WARNING! SELL TP ",tp,", Ask ",Ask," (Ask-TP = ",NormalizeDouble((Ask-tp)/_Point,_Digits),") WITHIN STOP LEVEL OF ",stopLevel);
|
|
return (false);
|
|
}
|
|
if (sl > 0 && sl - Ask < stopLevel_Pts){
|
|
Print("WARNING! SELL SL ",sl,", Ask ",Ask," (SL-Ask = ",NormalizeDouble((sl-Ask)/_Point,_Digits),") WITHIN STOP LEVEL OF ",stopLevel);
|
|
return (false);
|
|
}
|
|
|
|
// FREEZE LEVELS CHECK
|
|
if (tp > 0 && Ask - tp < freezeLevel_Pts){
|
|
Print("WARNING! SELL TP ",tp,", Ask ",Ask," (Ask-TP = ",NormalizeDouble((Ask-tp)/_Point,_Digits),") WITHIN FREEZE LEVEL OF ",freezeLevel);
|
|
return (false);
|
|
}
|
|
if (sl > 0 && sl - Ask < freezeLevel_Pts){
|
|
Print("WARNING! SELL SL ",sl,", Ask ",Ask," (SL-Ask = ",NormalizeDouble((sl-Ask)/_Point,_Digits),") WITHIN FREEZE LEVEL OF ",freezeLevel);
|
|
return (false);
|
|
}
|
|
}
|
|
|
|
if (tkt > 0){
|
|
bool result = PositionSelectByTicket(tkt);
|
|
if (result == false){
|
|
Print("ERROR Selecting The Position (CHECK) With Ticket # ",tkt);
|
|
return (false);
|
|
}
|
|
double point = SymbolInfoDouble(_Symbol,SYMBOL_POINT);
|
|
double pos_SL = PositionGetDouble(POSITION_SL);
|
|
double pos_TP = PositionGetDouble(POSITION_TP);
|
|
|
|
bool slChanged = MathAbs(pos_SL - sl) > point;
|
|
bool tpChanged = MathAbs(pos_TP - tp) > point;
|
|
|
|
//bool slChanged = pos_SL != sl;
|
|
//bool tpChanged = pos_TP != tp;
|
|
|
|
if (!slChanged && !tpChanged){
|
|
Print("ERROR. Pos # ",tkt," Already has Levels of SL: ",pos_SL,
|
|
", TP: ",pos_TP," NEW[SL = ",sl," | TP = ",tp,"]. NO POINT IN MODIFYING!!!");
|
|
return (false);
|
|
}
|
|
}
|
|
|
|
return (true);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 5. CHECK & CORRECT TRADE LEVELS |
|
|
//+------------------------------------------------------------------+
|
|
|
|
double Check5_TradeLevels_Rectify(ENUM_POSITION_TYPE pos_Type,double sl=0,double tp=0){
|
|
double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
|
|
double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
|
|
|
|
int stopLevel = (int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL);
|
|
int freezeLevel = (int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_FREEZE_LEVEL);
|
|
int spread = (int)SymbolInfoInteger(_Symbol,SYMBOL_SPREAD);
|
|
|
|
double stopLevel_Pts = stopLevel*_Point;
|
|
double freezeLevel_Pts = freezeLevel*_Point;
|
|
|
|
double accepted_price = 0.0;
|
|
|
|
if (pos_Type == POSITION_TYPE_BUY){
|
|
// STOP LEVELS CHECK
|
|
if (tp > 0 && tp - Bid < stopLevel_Pts){
|
|
accepted_price = Bid+stopLevel_Pts;
|
|
Print("WARNING! BUY TP ",tp,", Bid ",Bid," (TP-Bid = ",NormalizeDouble((tp-Bid)/_Point,_Digits),") WITHIN STOP LEVEL OF ",stopLevel);
|
|
Print("PRICE MODIFIED TO: ",accepted_price);
|
|
return (accepted_price);
|
|
}
|
|
if (sl > 0 && Bid - sl < stopLevel_Pts){
|
|
accepted_price = Bid-stopLevel_Pts;
|
|
Print("WARNING! BUY SL ",sl,", Bid ",Bid," (Bid-SL = ",NormalizeDouble((Bid-sl)/_Point,_Digits),") WITHIN STOP LEVEL OF ",stopLevel);
|
|
Print("PRICE MODIFIED TO: ",accepted_price);
|
|
return (accepted_price);
|
|
}
|
|
// FREEZE LEVELS CHECK
|
|
if (tp > 0 && tp - Bid < freezeLevel_Pts){
|
|
accepted_price = Bid+freezeLevel_Pts;
|
|
Print("WARNING! BUY TP ",tp,", Bid ",Bid," (TP-Bid = ",NormalizeDouble((tp-Bid)/_Point,_Digits),") WITHIN FREEZE LEVEL OF ",freezeLevel);
|
|
Print("PRICE MODIFIED TO: ",accepted_price);
|
|
return (accepted_price);
|
|
}
|
|
if (sl > 0 && Bid - sl < freezeLevel_Pts){
|
|
accepted_price = Bid-freezeLevel_Pts;
|
|
Print("WARNING! BUY SL ",sl,", Bid ",Bid," (Bid-SL = ",NormalizeDouble((Bid-sl)/_Point,_Digits),") WITHIN FREEZE LEVEL OF ",freezeLevel);
|
|
Print("PRICE MODIFIED TO: ",accepted_price);
|
|
return (accepted_price);
|
|
}
|
|
}
|
|
if (pos_Type == POSITION_TYPE_SELL){
|
|
// STOP LEVELS CHECK
|
|
if (tp > 0 && Ask - tp < stopLevel_Pts){
|
|
accepted_price = Ask-stopLevel_Pts;
|
|
Print("WARNING! SELL TP ",tp,", Ask ",Ask," (Ask-TP = ",NormalizeDouble((Ask-tp)/_Point,_Digits),") WITHIN STOP LEVEL OF ",stopLevel);
|
|
Print("PRICE MODIFIED TO: ",accepted_price);
|
|
return (accepted_price);
|
|
}
|
|
if (sl > 0 && sl - Ask < stopLevel_Pts){
|
|
accepted_price = Ask+stopLevel_Pts;
|
|
Print("WARNING! SELL SL ",sl,", Ask ",Ask," (SL-Ask = ",NormalizeDouble((sl-Ask)/_Point,_Digits),") WITHIN STOP LEVEL OF ",stopLevel);
|
|
Print("PRICE MODIFIED TO: ",accepted_price);
|
|
return (accepted_price);
|
|
}
|
|
|
|
// FREEZE LEVELS CHECK
|
|
if (tp > 0 && Ask - tp < freezeLevel_Pts){
|
|
accepted_price = Ask-freezeLevel_Pts;
|
|
Print("WARNING! SELL TP ",tp,", Ask ",Ask," (Ask-TP = ",NormalizeDouble((Ask-tp)/_Point,_Digits),") WITHIN FREEZE LEVEL OF ",freezeLevel);
|
|
Print("PRICE MODIFIED TO: ",accepted_price);
|
|
return (accepted_price);
|
|
}
|
|
if (sl > 0 && sl - Ask < freezeLevel_Pts){
|
|
accepted_price = Ask+freezeLevel_Pts;
|
|
Print("WARNING! SELL SL ",sl,", Ask ",Ask," (SL-Ask = ",NormalizeDouble((sl-Ask)/_Point,_Digits),") WITHIN FREEZE LEVEL OF ",freezeLevel);
|
|
Print("PRICE MODIFIED TO: ",accepted_price);
|
|
return (accepted_price);
|
|
}
|
|
}
|
|
return (accepted_price);
|
|
}
|