2026-01-02 15:37:26 +03:00
//+------------------------------------------------------------------+
//| Grid_2.mq5 |
//| AK47 |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
# property copyright " AK47 "
# property link " https://www.mql5.com "
# property version " 1.00 "
///////INCLUDE//////////
# include <Trade\Trade.mqh>
# include <Trade\OrderInfo.mqh>
# include <Trade\SymbolInfo.mqh>
# include <Trade\AccountInfo.mqh>
# include <Trade\DealInfo.mqh>
# include <Trade\PositionInfo.mqh>
# include <Arrays\ArrayDouble.mqh>
//#include <News.mqh>
//#include <Time.mqh>
////////GLOBALS//////////////
enum Side
{
Buy = 0 , // Buy
Sell = 1 , // Sell
Both = 2 , // Both
} ;
input double FixedLot = 0.01 ; // Fixed Lot
input Side EntrySide = 2 ;
input double TakeProfitFactor = 2 ;
double StopLossFactor = 3 ;
input ushort Grid = 250 ; // Grid Distance
//input double CloseTreshold=1.05;
//input double FreeMarginThreshold=0.3;
//input double EquityStopLossPercent=0.9;
input int PositionsThreshold = 2 ;
input double stDev = 1 ; // deviation
int MALength = 12 ;
input int bandsLength = 18 ;
int ATR1Length = 12 ;
int ATR2Length = 12 ;
input double Grid_mul = 1.2 , Vol_Mul = 1.8 ;
input string GMTstartTime = " 11:30 " ;
input string GMTendTime = " 17:30 " ;
2026-01-12 09:52:32 +03:00
input ENUM_TIMEFRAMES TimeFrame = PERIOD_M5 ; // Entry Time Frame
input ENUM_TIMEFRAMES MktStTimeFrame = PERIOD_M5 ; // Market Structure Time Frame
2026-01-02 15:37:26 +03:00
////////////CLASSES////////////////////
CTrade trade ;
CDealInfo deal ;
CPositionInfo PosInfo ;
CArrayDouble List ;
CAccountInfo Account ;
COrderInfo OrdInfo ;
//CNews News;
//CTime Time;
//////////VARIABLES/////////////
double MAHigh [ ] , MAHighData , MAHighHandle ,
MALow [ ] , MALowData , MALowHandle ,
MA [ ] , MAData , MAHandle , Momentum [ ] , MomentumData , MomentumHandle ,
bands [ ] , bandsupper [ ] , bandslower [ ] , bandsHandle , bandsData ,
MFI [ ] , MFIData , MFIHandle ,
ATR1 [ ] , ATR2 [ ] , ATR1Data , ATR2Data , ATR1Handle , ATR2Handle ;
2026-01-12 09:52:32 +03:00
double ask , bid , tradeVolume ,
2026-01-02 15:37:26 +03:00
StopLossBuy = 0 , StopLossSell = 0 ,
TakeProfitBuy = 0 , TakeProfitSell = 0 ,
StartingBalance ,
spread ,
buyFactor , sellFactor ,
Grid_step_buy ,
Grid_step_sell ,
currentGrid ,
nextUpBuy , nextDownBuy ,
nextUpSell , nextDownSell ,
currentUpBuy , currentDownBuy ,
currentUpSell , currentDownSell ,
meanEntry ;
int upCount = 0 , downCount = 0 ;
double maxEquity , equityVolume = 1 ;
string newGrid , previousGrid ;
double buyVolumeFactor = 1 , sellVolumeFactor = 1 ,
buyVolume , sellVolume ;
bool activateSL = false , buyStopSwitch = false , sellStopSwitch = false , buyLimitSwitch = false , sellLimitSwitch = false ;
MqlRates Bar1 [ ] , Bar2 [ ] ;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit ( )
{
//---
// News.LoadHistory();
StartingBalance = Account . Balance ( ) ;
ChartSetSymbolPeriod ( 0 , _Symbol , TimeFrame ) ;
MAHighHandle = iMA ( _Symbol , TimeFrame , MALength , 0 , MODE_EMA , PRICE_HIGH ) ;
MAHandle = iMA ( _Symbol , TimeFrame , MALength , 0 , MODE_EMA , PRICE_CLOSE ) ;
MALowHandle = iMA ( _Symbol , TimeFrame , MALength , 0 , MODE_EMA , PRICE_LOW ) ;
bandsHandle = iBands ( _Symbol , TimeFrame , bandsLength , 0 , stDev , PRICE_TYPICAL ) ;
2026-01-12 09:52:32 +03:00
//ATR1Handle = iATR(_Symbol,TimeFrame,ATR1Length);
//ATR2Handle = iATR(_Symbol,PERIOD_H1,ATR2Length);
2026-01-02 15:37:26 +03:00
MomentumHandle = iMomentum ( _Symbol , TimeFrame , 21 , PRICE_MEDIAN ) ;
ArraySetAsSeries ( MFI , true ) ;
ArraySetAsSeries ( ATR1 , true ) ;
ArraySetAsSeries ( ATR2 , true ) ;
ArraySetAsSeries ( MAHigh , true ) ;
ArraySetAsSeries ( MA , true ) ;
ArraySetAsSeries ( MALow , true ) ;
ArraySetAsSeries ( bands , true ) ;
ArraySetAsSeries ( bandsupper , true ) ;
ArraySetAsSeries ( bandslower , true ) ;
ArraySetAsSeries ( Bar1 , true ) ;
ArraySetAsSeries ( Bar2 , true ) ;
ArraySetAsSeries ( Momentum , true ) ;
bid = NormalizeDouble ( SymbolInfoDouble ( _Symbol , SYMBOL_BID ) , _Digits ) ;
ask = NormalizeDouble ( SymbolInfoDouble ( _Symbol , SYMBOL_ASK ) , _Digits ) ;
// double Prices[];
// double Volumes[];
// double levelstep = 5;
// CalculateVolumeDistribution(3,levelstep,Volumes,Prices);
//
// int peaks[];
// int peak_count = ArrayPeaks(Prices,peaks,100);
//
//
// FindIndices((ask+bid)/2,Prices,nextDown,nextUp);
nextUpBuy = ask + Grid * _Point ;
nextDownBuy = bid - Grid * _Point ;
nextUpSell = ask + Grid * _Point ;
nextDownSell = bid - Grid * _Point ;
Print ( " Buy NextLevelUp: " + nextUpBuy ) ;
Print ( " Buy NextLevelDown: " + nextDownBuy ) ;
Print ( " Sell NextLevelUp: " + nextUpSell ) ;
Print ( " Sell NextLevelDown: " + nextDownSell ) ;
//Print("PeaksCount: " + peak_count);
//---
return ( INIT_SUCCEEDED ) ;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit ( const int reason )
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick ( )
{
2026-01-05 14:39:26 +03:00
//CloseByWin();
2026-01-02 15:37:26 +03:00
//Trailing();
2026-01-05 14:39:26 +03:00
//breakEven();
2026-01-02 15:37:26 +03:00
//TPmodify();
2026-01-12 09:52:32 +03:00
tradeVolume = iVolume ( _Symbol , PERIOD_H1 , 0 ) ;
2026-01-02 15:37:26 +03:00
MqlDateTime dt ;
datetime gmtTime = TimeGMT ( dt ) ;
bid = NormalizeDouble ( SymbolInfoDouble ( _Symbol , SYMBOL_BID ) , _Digits ) ;
ask = NormalizeDouble ( SymbolInfoDouble ( _Symbol , SYMBOL_ASK ) , _Digits ) ;
spread = ask - bid ;
//////////////TP&SL//////////////////////////////////////////
MAHighData = CopyBuffer ( MAHighHandle , 0 , 0 , 4 , MAHigh ) ;
MAData = CopyBuffer ( MAHandle , 0 , 0 , 4 , MA ) ;
MALowData = CopyBuffer ( MALowHandle , 0 , 0 , 4 , MALow ) ;
ATR1Data = CopyBuffer ( ATR1Handle , 0 , 0 , 15 , ATR1 ) ;
ATR2Data = CopyBuffer ( ATR2Handle , 0 , 0 , 15 , ATR2 ) ;
bandsData = CopyBuffer ( bandsHandle , 0 , 0 , 4 , bands ) ;
bandsData = CopyBuffer ( bandsHandle , 1 , 0 , 4 , bandsupper ) ;
bandsData = CopyBuffer ( bandsHandle , 2 , 0 , 4 , bandslower ) ;
2026-01-05 14:39:26 +03:00
MomentumData = CopyBuffer ( MomentumHandle , 0 , 0 , 4 , Momentum ) ;
2026-01-02 15:37:26 +03:00
CopyRates ( _Symbol , TimeFrame , 0 , 10 , Bar1 ) ;
2026-01-12 09:52:32 +03:00
CopyRates ( _Symbol , MktStTimeFrame , 0 , 10 , Bar2 ) ;
2026-01-02 15:37:26 +03:00
// TakeProfitBuy = bid+Grid_step*TakeProfitFactor*_Point;
// TakeProfitSell = ask-Grid_step*TakeProfitFactor*_Point;
StopLossBuy = bands [ 1 ] ;
StopLossSell = bands [ 1 ] ;
//////////////////// Factors //////////////////////////////////
if ( BuyPositionsCount ( ) ! = 0 )
buyVolumeFactor = NormalizeDouble ( MathPow ( Vol_Mul , BuyPositionsCount ( ) ) , 0 ) ;
else
{
buyVolumeFactor = 1 ;
// Grid_step = Grid;
}
if ( SellPositionsCount ( ) ! = 0 )
sellVolumeFactor = NormalizeDouble ( MathPow ( Vol_Mul , SellPositionsCount ( ) ) , 0 ) ;
else
{
sellVolumeFactor = 1 ;
}
if ( PositionsTotal ( ) < 1 )
{
Grid_step_buy = Grid ;
Grid_step_sell = Grid ;
}
2026-01-12 09:52:32 +03:00
//int babar = 0;
//Comment(tradeVolume);
// if(babar < iBars(_Symbol,MktStTimeFrame))
// {
// IdentifyFractalLevels(100,1,MktStTimeFrame);
//
// babar = iBars(_Symbol,MktStTimeFrame);
// }
2026-01-02 15:37:26 +03:00
///////////////////BALANCEGRID//////////////////////////////////
2026-01-29 11:56:59 +03:00
string expire_date = " 2026.02.14 " ; //<-- hard coded datetime
2026-01-02 15:37:26 +03:00
datetime e_d = StringToTime ( expire_date ) ;
bool tradetime = true ; // (dt.hour == 8 || dt.hour == 14 || dt.hour == 0 || dt.hour == 1);
//bool tradetime = ((StringToTime(GMTstartTime) < StringToTime(GMTendTime) && gmtTime >= StringToTime(GMTstartTime) && gmtTime <= StringToTime(GMTendTime)) || (StringToTime(GMTstartTime) > StringToTime(GMTendTime) && gmtTime <= StringToTime(GMTstartTime) && gmtTime >= StringToTime(GMTendTime)));
//bool tradays = !((dt.day >= 1 && dt.day <= 7 && dt.day_of_week == 5) || (dt.day >= 10 && dt.day <=13) || (dt.day == 16 && dt.mon == 10));
if ( TimeCurrent ( ) < = e_d ) //spread<1500*_Point){
{
Grid_step_buy = Grid * MathPow ( Grid_mul , BuyPositionsCount ( ) ) ;
Grid_step_sell = Grid * MathPow ( Grid_mul , SellPositionsCount ( ) ) ;
buyVolumeFactor = MathPow ( Vol_Mul , BuyPositionsCount ( ) ) ;
sellVolumeFactor = MathPow ( Vol_Mul , SellPositionsCount ( ) ) ;
buyVolume = NormalizeDouble ( equityVolume * buyVolumeFactor * FixedLot , 2 ) ;
sellVolume = NormalizeDouble ( equityVolume * sellVolumeFactor * FixedLot , 2 ) ;
//double meanATR1 = ArrayCountAverage(ATR1,3);
//double meanATR2 = ArrayCountAverage(ATR2,3);
//Print("bands: " + bands[1]);
//Comment("\MATR~1: " + meanATR1 + "MATR~2 " + meanATR2);
//--- BuyLimit
if ( ask < nextDownBuy )
{
buyLimitSwitch = true ;
currentDownBuy = nextDownBuy ;
nextUpBuy = ask + Grid_step_buy * _Point ;
nextDownBuy = bid - Grid_step_buy * _Point ;
}
//if((CheckFractalTrend(10) != "Bullish" && CheckFractalTrend(1) != "Bearish") && tradetime && (EntrySide == 2 || EntrySide == 0) && buyLimitSwitch && currentDownBuy + 100*_Point && !OtherBuyPosition(NULL) && ask > bands[1] && ask < bandslower[0])
// {
// trade.Buy(buyVolume,_Symbol,0,0,TakeProfitBuy,"BuyLimit");
// buyLimitSwitch = false;
// }
//--- BuyStop
if ( ask > nextUpBuy )
{
buyStopSwitch = true ;
currentUpBuy = nextUpBuy ;
nextUpBuy = ask + Grid_step_buy * _Point ;
nextDownBuy = ask - Grid_step_buy * _Point ;
}
2026-01-12 09:52:32 +03:00
if ( tradeVolume > 10000 & & tradetime & & ( EntrySide = = 2 | | EntrySide = = 0 ) & & buyStopSwitch & & currentUpBuy - 5 * _Point & & ! OtherBuyPosition ( NULL ) & & ask > bandsupper [ 1 ] )
//&& Bar1[1].high > Bar1[2].highCheckFractalTrend(10) == "Bullish" &&
2026-01-02 15:37:26 +03:00
{
trade . Buy ( buyVolume , _Symbol , 0 , StopLossBuy , TakeProfitBuy , " BuyStop " ) ;
buyStopSwitch = false ;
}
//--- SellLimit
if ( bid > nextUpSell )
{
sellLimitSwitch = true ;
currentUpSell = nextUpSell ;
nextUpSell = bid + Grid_step_sell * _Point ;
nextDownSell = bid - Grid_step_sell * _Point ;
}
//if((CheckFractalTrend(10) != "Bullish" && CheckFractalTrend(1) != "Bearish") && tradetime && (EntrySide == 2 || EntrySide == 1) && sellLimitSwitch && currentUpSell - 100*_Point && !OtherSellPosition(NULL) && bid > bands[1] && bid < bandsupper[0])
//{
// trade.Sell(sellVolume,_Symbol,0,StopLossSell,TakeProfitSell,"SellLimit");
// sellLimitSwitch = false;
//}
//--- SellStop
if ( bid < nextDownSell ) // && bid > currentDownSell + 10*_Point && ask < currentUpBuyStop - 10*_Point
{
sellStopSwitch = true ;
currentDownSell = nextDownSell ;
nextUpSell = bid + Grid_step_sell * _Point ;
nextDownSell = bid - Grid_step_sell * _Point ;
}
2026-01-12 09:52:32 +03:00
if ( tradeVolume > 10000 & & tradetime & & ( EntrySide = = 2 | | EntrySide = = 1 ) & & sellStopSwitch & & currentDownSell + 5 * _Point & & ! OtherSellPosition ( NULL ) & & bid < bandslower [ 1 ] )
//&& Bar1[1].low < Bar1[2].lowCheckFractalTrend(10) == "Bearish" &&
2026-01-02 15:37:26 +03:00
{
trade . Sell ( sellVolume , _Symbol , 0 , StopLossSell , TakeProfitSell , " SellStop " ) ;
sellStopSwitch = false ;
}
}
else
{
Comment ( " Your license is expired! " ) ;
}
//////////////////////CLOSERS//////////////////////////////////////////////
2026-01-12 09:52:32 +03:00
//if(tradeVolume < 8000)
// {
2026-01-02 15:37:26 +03:00
StoplossUpdate ( " buy " ) ;
StoplossUpdate ( " sell " ) ;
2026-01-12 09:52:32 +03:00
//}
2026-01-02 15:37:26 +03:00
if ( Account . Equity ( ) > maxEquity & & PositionsTotal ( ) < 2 )
{
maxEquity = Account . Equity ( ) ;
//equityVolume = MathCeil(maxEquity/10000);
//if(VolumeTotal("Total") > StartingBalance/1000)
//{
// CloseAllPositions();
//}
}
if ( Account . Equity ( ) > = 1.01 * maxEquity )
{
activateSL = true ;
maxEquity = Account . Equity ( ) ;
}
if ( activateSL & & Account . Equity ( ) < = 1 / ( 1.01 ) * maxEquity )
{
activateSL = false ;
//CloseAllPositions();
}
}
//+------------------------------------------------------------------+
//| Trade function |
//+------------------------------------------------------------------+
void OnTrade ( )
{
//---
}
/// Global arrays to store fractal highs and lows
double fractalHighs [ ] ;
double fractalLows [ ] ;
2026-01-12 09:52:32 +03:00
double fractalHighsTime [ ] ;
double fractalLowsTime [ ] ;
int fractalHighsIndex [ ] ;
int fractalLowsIndex [ ] ;
2026-01-02 15:37:26 +03:00
MqlRates Bar3 [ ] ;
//Function to identify fractal bars and store their levels
void IdentifyFractalLevels ( int period , int n , ENUM_TIMEFRAMES TF )
{
// Ensure the period is valid
if ( period < n )
{
Print ( " Period must be at least " , n ) ;
return ;
}
// Resize arrays to the specified period
double highs [ ] ;
double lows [ ] ;
ArrayResize ( highs , period ) ;
ArrayResize ( lows , period ) ;
// Copy high and low prices for the given period
if ( CopyHigh ( _Symbol , TF , 0 , period , highs ) < = 0 | | CopyLow ( _Symbol , TF , 0 , period , lows ) < = 0 ) // || CopyTime(_Symbol, TF, 0, period, time) <= 0)
{
Print ( " Failed to copy price data. " ) ;
return ;
}
if ( CopyRates ( _Symbol , TF , 0 , period , Bar3 ) < = 0 )
{
Print ( " Failed to copy rates " ) ;
return ;
}
// Clear previous fractal data
ArrayResize ( fractalHighs , 0 ) ;
ArrayResize ( fractalLows , 0 ) ;
2026-01-12 09:52:32 +03:00
ArrayResize ( fractalHighsTime , 0 ) ;
ArrayResize ( fractalLowsTime , 0 ) ;
ArrayResize ( fractalHighsIndex , 0 ) ;
ArrayResize ( fractalLowsIndex , 0 ) ;
2026-01-02 15:37:26 +03:00
// Adjust the loop to find local maxima and minima for n bars around the highest/lowest bar
for ( int i = n ; i < period - n ; i + + )
{
bool isLocalMax = true ;
bool isLocalMin = true ;
// Check for local maximum
for ( int j = 1 ; j < = n ; j + + )
{
if ( highs [ i ] < = highs [ i + j ] | | highs [ i ] < = highs [ i - j ] )
{
isLocalMax = false ;
break ;
}
}
if ( isLocalMax )
{
ArrayResize ( fractalHighs , ArraySize ( fractalHighs ) + 1 ) ;
fractalHighs [ ArraySize ( fractalHighs ) - 1 ] = highs [ i ] ;
2026-01-12 09:52:32 +03:00
ArrayResize ( fractalHighsTime , ArraySize ( fractalHighsTime ) + 1 ) ;
fractalHighsTime [ ArraySize ( fractalHighsTime ) - 1 ] = ( double ) Bar3 [ i ] . time ;
ArrayResize ( fractalHighsIndex , ArraySize ( fractalHighsIndex ) + 1 ) ;
fractalHighsIndex [ ArraySize ( fractalHighsIndex ) - 1 ] = i ;
2026-01-02 15:37:26 +03:00
// DrawArrow(highs[i],i,"top", clrRed);
}
// Check for local minimum
for ( int j = 1 ; j < = n ; j + + )
{
if ( lows [ i ] > = lows [ i + j ] | | lows [ i ] > = lows [ i - j ] )
{
isLocalMin = false ;
break ;
}
}
if ( isLocalMin )
{
ArrayResize ( fractalLows , ArraySize ( fractalLows ) + 1 ) ;
fractalLows [ ArraySize ( fractalLows ) - 1 ] = lows [ i ] ;
2026-01-12 09:52:32 +03:00
ArrayResize ( fractalLowsTime , ArraySize ( fractalLowsTime ) + 1 ) ;
fractalLowsTime [ ArraySize ( fractalLowsTime ) - 1 ] = ( double ) Bar3 [ i ] . time ;
ArrayResize ( fractalLowsIndex , ArraySize ( fractalLowsIndex ) + 1 ) ;
fractalLowsIndex [ ArraySize ( fractalLowsIndex ) - 1 ] = i ;
2026-01-02 15:37:26 +03:00
//
// DrawArrow(lows[i],i,"bottom", clrRed);
}
}
2026-01-12 09:52:32 +03:00
////Print the fractal highs and lows for debugging
// for(int i = 0; i < ArraySize(fractalHighs); i++)
// {
// Print("Fractal High at index ", i, ": ", fractalHighs[i]);
// }
// for(int i = 0; i < ArraySize(fractalLows); i++)
// {
// Print("Fractal Low at index ", i, ": ", fractalLows[i]);
// }
//
2026-01-02 15:37:26 +03:00
}
// Function to draw an arrow on the chart
void DrawArrow ( double priceLevel , int index , string arrowPosition , color arrowColor )
{
// Create a unique name for the arrow object
string arrowName = " Arrow_ " + IntegerToString ( index ) + " _ " + arrowPosition ;
int arrowCode = 0 ;
// Determine the y-coordinate for the arrow based on the position (top or bottom)
double yCoordinate = priceLevel ;
if ( arrowPosition = = " top " )
{
// Place the arrow above the bar
yCoordinate + = 10 * Point ( ) ; // Adjust the multiplier as needed
arrowCode = 233 ;
}
else if ( arrowPosition = = " bottom " )
{
// Place the arrow below the bar
yCoordinate - = 10 * Point ( ) ; // Adjust the multiplier as needed
arrowCode = 234 ;
}
// Create the arrow object
if ( ! ObjectCreate ( 0 , arrowName , OBJ_ARROW , 0 , index , yCoordinate ) )
{
//Print("Failed to create arrow object: ", arrowName);
return ;
}
// Set the properties of the arrow
ObjectSetInteger ( 0 , arrowName , OBJPROP_ARROWCODE , arrowCode ) ;
ObjectSetInteger ( 0 , arrowName , OBJPROP_COLOR , arrowColor ) ;
ObjectSetInteger ( 0 , arrowName , OBJPROP_WIDTH , 1 ) ; // Set the width of the arrow
ObjectSetInteger ( 0 , arrowName , OBJPROP_SELECTABLE , false ) ;
ObjectSetInteger ( 0 , arrowName , OBJPROP_HIDDEN , true ) ;
ObjectSetInteger ( 0 , arrowName , OBJPROP_ZORDER , 0 ) ;
}
//-----------------------------------------------------------------------+
// Function to determine the trend based on fractal highs and lows |
//-----------------------------------------------------------------------+
string CheckFractalTrend ( int n )
{
// Ensure there are enough data points to analyze
if ( ArraySize ( fractalHighs ) < 2 | | ArraySize ( fractalLows ) < 2 )
{
//Print("Not enough fractal data to determine trend.");
return " Not enough fractal data to determine trend. " ;
}
// Initialize flags for trend detection
bool higherHighs = false ;
bool lowerLows = false ;
bool higherLows = false ;
bool lowerHighs = false ;
// modify to Check only the last n values from fractal highs and lows
// To modify the code to check only the last `n` values from fractal highs and lows, you need to iterate over the last `n` elements of the `fractalHighs` and `fractalLows` arrays. You can achieve this by using a loop that starts from the end of the array and goes back `n` elements. Here's how you can modify your code:
//
// Define the number of last values to check
// Check the last n values for fractal higherhighs
//for(int i = ArraySize(fractalHighs) - 1; i >= ArraySize(fractalHighs) - n; i--)
//{
2026-01-12 09:52:32 +03:00
// if(i <= 0)
// break; // Ensure we don't go out of bounds
2026-01-02 15:37:26 +03:00
if ( fractalHighs [ ArraySize ( fractalHighs ) -1 ] > fractalHighs [ ArraySize ( fractalHighs ) - 2 ] )
{
higherHighs = true ;
//break;
}
//}
2026-01-12 09:52:32 +03:00
// Check the last n values for fractal lowerlows
//for(int i = ArraySize(fractalLows) - 1; i >= ArraySize(fractalLows) - n; i--)
//{
// if(i <= 0)
// break; // Ensure we don't go out of bounds
2026-01-02 15:37:26 +03:00
if ( fractalLows [ ArraySize ( fractalLows ) -1 ] < fractalLows [ ArraySize ( fractalLows ) - 2 ] )
{
lowerLows = true ;
//break;
}
//}
2026-01-12 09:52:32 +03:00
////// Check the last n values for fractal higherlows
2026-01-02 15:37:26 +03:00
// for(int i = ArraySize(fractalLows) - 1; i >= ArraySize(fractalLows) - n; i--)
// {
// if(i <= 0)
// break; // Ensure we don't go out of bounds
//
if ( fractalLows [ ArraySize ( fractalLows ) -1 ] > fractalLows [ ArraySize ( fractalLows ) - 2 ] )
{
higherLows = true ;
//break;
}
//}
//// Check the last n values for fractal lows
2026-01-12 09:52:32 +03:00
//for(int i = ArraySize(fractalHighs) - 1; i >= ArraySize(fractalHighs) - n; i--)
//{
// if(i <= 0)
// break; // Ensure we don't go out of bounds
2026-01-02 15:37:26 +03:00
if ( fractalHighs [ ArraySize ( fractalHighs ) -1 ] < fractalHighs [ ArraySize ( fractalHighs ) - 2 ] )
{
lowerHighs = true ;
//break;
}
//}
// Now higherHighs and lowerLows will reflect the result of checking the last n values
//
// ### Explanation:
// - **Loop Setup**: The loops iterate from the last element of the array to the element `n` positions back. This ensures that only the last `n` elements are checked.
// - **Boundary Check**: The `if(i <= 0) break;` statement ensures that the loop does not attempt to access an element before the start of the array, which would cause an out-of-bounds error.
// - **Condition Check**: The conditions inside the loops check if the current element is less than or greater than the previous one, updating the `higherHighs` and `lowerLows` flags accordingly.
// - **Flags**: The `higherHighs` and `lowerLows` flags are set to `true` initially and are only set to `false` if a condition is not met during the iteration. This means that if all conditions are met, the flags remain `true`.
//
// Determine and print the trend
if ( higherHighs & & lowerLows )
{
//Print("The fractals are making undefined moves (notrend).");
2026-01-12 09:52:32 +03:00
//Comment("?????");
2026-01-02 15:37:26 +03:00
return " undefined " ;
}
2026-01-12 09:52:32 +03:00
if ( higherHighs & & higherLows )
2026-01-02 15:37:26 +03:00
{
//Print("The fractals are making higher highs (uptrend).");
//Comment("BULL");
return " Bullish " ;
}
2026-01-12 09:52:32 +03:00
if ( lowerLows & & lowerHighs )
2026-01-02 15:37:26 +03:00
{
//Print("The fractals are making lower lows (downtrend).");
//Comment("BEAR");
return " Bearish " ;
}
2026-01-12 09:52:32 +03:00
if ( lowerHighs & & higherLows )
2026-01-02 15:37:26 +03:00
{
//Print("The fractals do not show a clear trend.");
//Comment("???");
return " unclear. " ;
}
2026-01-12 09:52:32 +03:00
return 0 ;
2026-01-02 15:37:26 +03:00
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double ArrayCountAverage ( double & array [ ] , int count )
{
double sum ;
double mean ;
//if (ArraySize(array) < count - 1);
//{
// Print("Array has less elements than required for mean" + ArraySize(array) + " count: " + (count-1));
//}
for ( int i = 0 ; i < count -1 ; i + + )
{
sum + = array [ i ] - array [ i + 1 ] ;
}
mean = sum / ( count -1 ) ;
Print ( " Derivative is: " + mean ) ;
return mean ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double meanEntryPrice ( string type )
{
double quantity = 0 ;
double volume = 0 ;
double entry = 0 ;
for ( int i = PositionsTotal ( ) -1 ; i > = 0 ; i - - )
{
PositionGetTicket ( i ) ;
//////////////////////////////////
if ( type = = " Buy " & & PositionGetInteger ( POSITION_TYPE ) = = POSITION_TYPE_BUY & & PositionGetString ( POSITION_SYMBOL ) = = _Symbol )
{
quantity = quantity + PosInfo . Volume ( ) * PosInfo . PriceOpen ( ) ;
volume = volume + PosInfo . Volume ( ) ;
}
if ( type = = " Sell " & & PositionGetInteger ( POSITION_TYPE ) = = POSITION_TYPE_SELL & & PositionGetString ( POSITION_SYMBOL ) = = _Symbol )
{
quantity = quantity + PosInfo . Volume ( ) * PosInfo . PriceOpen ( ) ;
volume = volume + PosInfo . Volume ( ) ;
}
if ( type = = " Total " & & PositionGetString ( POSITION_SYMBOL ) = = _Symbol )
{
quantity = quantity + PosInfo . Volume ( ) * PosInfo . PriceOpen ( ) ;
volume = volume + PosInfo . Volume ( ) ;
}
if ( type = = " BuysAbove " & & PositionGetInteger ( POSITION_TYPE ) = = POSITION_TYPE_BUY & & PosInfo . PriceOpen ( ) > PosInfo . PriceCurrent ( ) & & PositionGetString ( POSITION_SYMBOL ) = = _Symbol )
{
quantity = quantity + PosInfo . Volume ( ) * PosInfo . PriceOpen ( ) ;
volume = volume + PosInfo . Volume ( ) ;
}
if ( type = = " BuysBelow " & & PositionGetInteger ( POSITION_TYPE ) = = POSITION_TYPE_BUY & & PosInfo . PriceOpen ( ) < PosInfo . PriceCurrent ( ) & & PositionGetString ( POSITION_SYMBOL ) = = _Symbol )
{
quantity = quantity + PosInfo . Volume ( ) * PosInfo . PriceOpen ( ) ;
volume = volume + PosInfo . Volume ( ) ;
}
/////////////////////////////
if ( type = = " SellsAbove " & & PosInfo . PositionType ( ) = = POSITION_TYPE_SELL & & PosInfo . PriceOpen ( ) > PosInfo . PriceCurrent ( ) & & PositionGetString ( POSITION_SYMBOL ) = = _Symbol )
{
quantity = quantity + PosInfo . Volume ( ) * PosInfo . PriceOpen ( ) ;
volume = volume + PosInfo . Volume ( ) ;
}
if ( type = = " SellsBelow " & & PosInfo . PositionType ( ) = = POSITION_TYPE_SELL & & PosInfo . PriceOpen ( ) < PosInfo . PriceCurrent ( ) & & PositionGetString ( POSITION_SYMBOL ) = = _Symbol )
{
quantity = quantity + PosInfo . Volume ( ) * PosInfo . PriceOpen ( ) ;
volume = volume + PosInfo . Volume ( ) ;
}
}
entry = quantity / volume ;
return entry ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double VolumeTotal ( string positionType )
{
double totalVolume = 0 ;
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
{
if ( PosInfo . SelectByIndex ( i ) & & positionType = = " Buy " & & PosInfo . PositionType ( ) = = POSITION_TYPE_BUY )
{
totalVolume + = PosInfo . Volume ( ) ;
}
}
//Print("BV: " + positionType + ": "+ totalVolume);
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - )
{
if ( PosInfo . SelectByIndex ( i ) & & positionType = = " Sell " & & PosInfo . PositionType ( ) = = POSITION_TYPE_SELL )
{
totalVolume + = PosInfo . Volume ( ) ;
}
}
//Print("SV: " + positionType + ": " + totalVolume);
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - )
{
if ( PosInfo . SelectByIndex ( i ) & & positionType = = " Total " )
{
totalVolume + = PosInfo . Volume ( ) ;
}
}
//Print("TV: " + positionType + ": " + totalVolume);
return totalVolume ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int FindIndices ( double value , double & arr [ ] , int & indexlow , int & indexhigh )
{
int size = ArraySize ( arr ) ;
// Check if the array has at least two elements
if ( size < 2 )
{
Print ( " Array must have at least two elements. " ) ;
// return -1; // Return -1 to indicate an error
}
// Iterate through the array to find the indices
for ( int i = 0 ; i < size - 1 ; i + + )
{
if ( ( value > arr [ i ] & & value < arr [ i + 1 ] ) | | ( value < arr [ i ] & & value > arr [ i + 1 ] ) )
{
indexlow = i ;
indexhigh = i + 1 ;
return 0 ; // Return 0 to indicate success
}
}
// If no such indices are found
Print ( " No indices found where the value is between two consecutive elements. " ) ;
return -1 ; // Return -1 to indicate failure
}
//+------------------------------------------------------------------+
void CalculateVolumeDistribution ( int Days , double levelStep , double & volumeArray [ ] , double & priceLevelArray [ ] )
{
// Determine the number of bars in two full days
int barsInFullDay = 1440 ; // 1440 minutes in a day
int barsInDays = Days * barsInFullDay ;
// Calculate the number of bars that have elapsed today
datetime currentTime = TimeCurrent ( ) ;
datetime startOfDay = currentTime - ( currentTime % 86400 ) ; // Start of the current day
int barsElapsedToday = ( int ) ( ( currentTime - startOfDay ) / 60 ) ; // Convert seconds to minutes
// Total lookback bars
int lookbackBars = barsInDays + barsElapsedToday ;
// Initialize variables to store the lowest low and highest high
double lowestLow = 0 ;
double highestHigh = 0 ;
// Arrays to store the data
double lowArray [ ] ;
double highArray [ ] ;
long volumeArrayRaw [ ] ;
// Copy the data for the specified number of bars
if ( CopyLow ( _Symbol , PERIOD_M1 , 0 , lookbackBars , lowArray ) < = 0 | |
CopyHigh ( _Symbol , PERIOD_M1 , 0 , lookbackBars , highArray ) < = 0 | |
CopyTickVolume ( _Symbol , PERIOD_M1 , 0 , lookbackBars , volumeArrayRaw ) < = 0 )
{
Print ( " Error copying data " ) ;
return ;
}
// Loop through the lookback period to find the lowest low and highest high
for ( int i = 0 ; i < lookbackBars ; i + + )
{
double low = lowArray [ i ] ;
double high = highArray [ i ] ;
if ( ( low ! = 0 & & low < lowestLow ) | | lowestLow = = 0 )
lowestLow = low ;
if ( high > highestHigh )
highestHigh = high ;
}
Print ( " Lowest Level: " , lowestLow ) ;
Print ( " Highest Level: " , highestHigh ) ;
// Calculate the number of levels
int numberOfLevels = int ( ( highestHigh - lowestLow ) / levelStep ) + 1 ;
// Resize the arrays to hold the data
ArrayResize ( volumeArray , numberOfLevels ) ;
ArrayResize ( priceLevelArray , numberOfLevels ) ;
// Initialize arrays
for ( int i = 0 ; i < numberOfLevels ; i + + )
{
volumeArray [ i ] = 0 ;
priceLevelArray [ i ] = lowestLow + i * levelStep ;
}
// Aggregate volume for each level
for ( int i = 0 ; i < lookbackBars ; i + + )
{
double low = lowArray [ i ] ;
double high = highArray [ i ] ;
double volume = ( double ) volumeArrayRaw [ i ] ;
// Determine which levels the current bar's range covers
int startLevel = int ( ( low - lowestLow ) / levelStep ) ;
int endLevel = int ( ( high - lowestLow ) / levelStep ) ;
// Distribute volume across the levels covered by the bar
for ( int level = startLevel ; level < = endLevel ; level + + )
{
if ( level > = 0 & & level < numberOfLevels )
{
volumeArray [ level ] + = volume ;
//Print("Level: ", level, " Volume: ", volumeArray[level]);
}
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int ArrayPeaks ( const double & array [ ] , int & peaks [ ] , double min_distance )
{
int LevelsToCheck = Grid ;
int array_size = ArraySize ( array ) ;
if ( array_size < LevelsToCheck )
return 0 ; // Return 0 if the array is too small to have peaks
int peak_count = 0 ;
ArrayResize ( peaks , array_size ) ; // Resize peaks array to the maximum possible size initially
// Iterate through the array to find peaks
for ( int i = ( int ) ( LevelsToCheck / 2 ) ; i < array_size - ( int ) ( LevelsToCheck / 2 ) ; i + + ) // Start from level index and end at array_size - level index
{
bool is_peak = true ;
// Check if the current element is greater than the elements in the range of indices around it
for ( int j = i - ( int ) ( LevelsToCheck / 2 ) ; j < = i + ( int ) ( LevelsToCheck / 2 ) ; j + + )
{
if ( j ! = i & & array [ i ] < = array [ j ] )
{
is_peak = false ;
break ;
}
}
if ( is_peak )
{
bool is_far_enough = true ;
for ( int j = 0 ; j < peak_count ; j + + )
{
if ( MathAbs ( i - peaks [ j ] ) < min_distance )
{
is_far_enough = false ;
break ;
}
}
if ( is_far_enough )
{
peaks [ peak_count ] = i ;
peak_count + + ;
}
}
}
ArrayResize ( peaks , peak_count ) ; // Resize peaks array to the actual number of peaks found
return peak_count ; // Return the number of peaks found
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CalculateValueArea ( const double & priceLevels [ ] , const double & volumes [ ] , double & valAreaHigh , double & valAreaLow , double percentage = 70.0 )
{
int size = ArraySize ( volumes ) ;
if ( size < = 0 | | size ! = ArraySize ( priceLevels ) )
{
//Print("Array Issue: Price Levels and Volumes don't match or are empty.");
return ;
}
// Calculate total volume
double totalVolume = 0.0 ;
for ( int i = 0 ; i < size ; i + + )
{
totalVolume + = volumes [ i ] ;
}
// Target volume for the value area
double targetVolume = totalVolume * ( percentage / 100.0 ) ;
// Find the POC
int pocIndex = 0 ;
double maxVolume = volumes [ 0 ] ;
for ( int i = 1 ; i < size ; i + + )
{
if ( volumes [ i ] > maxVolume )
{
maxVolume = volumes [ i ] ;
pocIndex = i ;
}
}
// Initialize the value area with the POC
valAreaLow = priceLevels [ pocIndex ] ;
valAreaHigh = priceLevels [ pocIndex ] ;
double cumulativeVolume = maxVolume ;
// Expand the value area around the POC
int leftIndex = pocIndex - 1 ;
int rightIndex = pocIndex + 1 ;
while ( cumulativeVolume < targetVolume )
{
// Consider both directions and choose the one with larger volume
if ( leftIndex > = 0 & & ( rightIndex > = size | | volumes [ leftIndex ] > = volumes [ rightIndex ] ) )
{
cumulativeVolume + = volumes [ leftIndex ] ;
valAreaLow = priceLevels [ leftIndex ] ;
leftIndex - - ;
}
else if ( rightIndex < size )
{
cumulativeVolume + = volumes [ rightIndex ] ;
valAreaHigh = priceLevels [ rightIndex ] ;
rightIndex + + ;
}
else
{
// No more price levels to consider
break ;
}
}
}
////////////////CLOSING FUNCTIONS////////////////////////////////////
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CloseAllPositions ( )
{
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
if ( PosInfo . SelectByIndex ( i ) ) // select a position
{
trade . PositionClose ( PosInfo . Ticket ( ) ) ;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CancelLimits ( string comment )
{
for ( int i = OrdersTotal ( ) -1 ; i > = 0 ; i - - )
if ( OrdInfo . SelectByIndex ( i ) & & PosInfo . Comment ( ) = = comment )
{
trade . OrderDelete ( OrdInfo . Ticket ( ) ) ;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CloseByWinning ( )
{
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
if ( PosInfo . SelectByIndex ( i ) )
{
if ( PosInfo . PositionType ( ) = = POSITION_TYPE_BUY )
{
double thebuy = PosInfo . PriceOpen ( ) ;
int theBuyTicket = PosInfo . Ticket ( ) ;
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - )
if ( PosInfo . SelectByIndex ( i ) )
{
if ( PosInfo . PositionType ( ) = = POSITION_TYPE_SELL )
{
double thesell = PosInfo . PriceOpen ( ) ;
int theSellTicket = PosInfo . Ticket ( ) ;
if ( thesell - thebuy > 0 )
{
trade . PositionCloseBy ( theBuyTicket , theSellTicket ) ;
}
}
}
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CloseByLosing ( )
{
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
if ( PosInfo . SelectByIndex ( i ) & & PosInfo . PositionType ( ) = = POSITION_TYPE_BUY )
{
double thebuy = PosInfo . PriceOpen ( ) ;
int theBuyTicket = PosInfo . Ticket ( ) ;
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - )
if ( PosInfo . SelectByIndex ( i ) & & PosInfo . PositionType ( ) = = POSITION_TYPE_SELL )
{
double thesell = PosInfo . PriceOpen ( ) ;
int theSellTicket = PosInfo . Ticket ( ) ;
if ( thesell - thebuy < - Grid * _Point )
{
trade . PositionCloseBy ( theBuyTicket , theSellTicket ) ;
}
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CloseByWin ( )
{
int profitTicket ;
double profit ;
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
if ( PosInfo . SelectByIndex ( i ) )
{
if ( PosInfo . PositionType ( ) = = POSITION_TYPE_BUY )
{
if ( PosInfo . Profit ( ) > profit )
{
profit = PosInfo . Profit ( ) ;
}
double thebuy = PosInfo . PriceOpen ( ) ;
int theBuyTicket = PosInfo . Ticket ( ) ;
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - )
if ( PosInfo . SelectByIndex ( i ) )
{
if ( PosInfo . PositionType ( ) = = POSITION_TYPE_SELL )
{
double thesell = PosInfo . PriceOpen ( ) ;
int theSellTicket = PosInfo . Ticket ( ) ;
if ( thesell - thebuy > 0 )
{
trade . PositionCloseBy ( theBuyTicket , theSellTicket ) ;
}
}
}
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CloseByLoss ( )
{
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
if ( PosInfo . SelectByIndex ( i ) & & PosInfo . PositionType ( ) = = POSITION_TYPE_BUY )
{
double thebuy = PosInfo . PriceOpen ( ) ;
int theBuyTicket = PosInfo . Ticket ( ) ;
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - )
if ( PosInfo . SelectByIndex ( i ) & & PosInfo . PositionType ( ) = = POSITION_TYPE_SELL )
{
double thesell = PosInfo . PriceOpen ( ) ;
int theSellTicket = PosInfo . Ticket ( ) ;
if ( thesell - thebuy < - Grid * _Point )
{
trade . PositionCloseBy ( theBuyTicket , theSellTicket ) ;
}
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CloseWinners ( )
{
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
if ( PosInfo . SelectByIndex ( i ) )
{
if ( PosInfo . Profit ( ) > 0 )
{
int Ticket = PosInfo . Ticket ( ) ;
trade . PositionClose ( Ticket ) ;
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CloseLosers ( )
{
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
if ( PosInfo . SelectByIndex ( i ) )
{
if ( PosInfo . Profit ( ) < 0 )
{
int Ticket = PosInfo . Ticket ( ) ;
trade . PositionClose ( Ticket ) ;
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CloseBuyWin ( )
{
double Profit ;
int ProfitTicket ;
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
{
if ( PosInfo . SelectByIndex ( i ) )
{
if ( PosInfo . PositionType ( ) = = POSITION_TYPE_BUY & & PosInfo . Profit ( ) > Profit & & PosInfo . Profit ( ) > 0 )
{
Profit = PosInfo . Profit ( ) ;
ProfitTicket = PosInfo . Ticket ( ) ;
}
}
}
trade . PositionClose ( ProfitTicket ) ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CloseSellWin ( )
{
double Profit ;
int ProfitTicket ;
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
{
if ( PosInfo . SelectByIndex ( i ) )
{
if ( PosInfo . PositionType ( ) = = POSITION_TYPE_SELL & & PosInfo . Profit ( ) > Profit & & PosInfo . Profit ( ) > 0 )
{
Profit = PosInfo . Profit ( ) ;
ProfitTicket = PosInfo . Ticket ( ) ;
}
}
}
trade . PositionClose ( ProfitTicket ) ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CloseBuyLoss ( )
{
double Profit ;
int ProfitTicket ;
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
{
if ( PosInfo . SelectByIndex ( i ) )
{
if ( PosInfo . PositionType ( ) = = POSITION_TYPE_BUY & & PosInfo . Profit ( ) < Profit & & PosInfo . Profit ( ) < 0 )
{
Profit = PosInfo . Profit ( ) ;
ProfitTicket = PosInfo . Ticket ( ) ;
}
}
}
trade . PositionClose ( ProfitTicket ) ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double HighestBuy ( )
{
double Price = 0 ;
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
{
if ( PosInfo . SelectByIndex ( i ) )
{
if ( PosInfo . PositionType ( ) = = POSITION_TYPE_BUY & & PosInfo . PriceOpen ( ) > Price )
{
Price = PosInfo . PriceOpen ( ) ;
}
}
}
return Price ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double HighestSell ( )
{
double Price = 0 ;
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
{
if ( PosInfo . SelectByIndex ( i ) )
{
if ( PosInfo . PositionType ( ) = = POSITION_TYPE_SELL & & PosInfo . PriceOpen ( ) > Price )
{
Price = PosInfo . PriceOpen ( ) ;
}
}
}
return Price ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double LowestBuy ( )
{
double Price = 2 ;
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
{
if ( PosInfo . SelectByIndex ( i ) )
{
if ( PosInfo . PositionType ( ) = = POSITION_TYPE_BUY & & PosInfo . PriceOpen ( ) < Price )
{
Price = PosInfo . PriceOpen ( ) ;
}
}
}
return Price ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double LowestSell ( )
{
double Price = 2 ;
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
{
if ( PosInfo . SelectByIndex ( i ) )
{
if ( PosInfo . PositionType ( ) = = POSITION_TYPE_SELL & & PosInfo . PriceOpen ( ) < Price )
{
Price = PosInfo . PriceOpen ( ) ;
}
}
}
return Price ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CloseSellLoss ( )
{
double Profit ;
int ProfitTicket ;
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
{
if ( PosInfo . SelectByIndex ( i ) )
{
if ( PosInfo . PositionType ( ) = = POSITION_TYPE_SELL & & PosInfo . Profit ( ) < Profit & & PosInfo . Profit ( ) < 0 )
{
Profit = PosInfo . Profit ( ) ;
ProfitTicket = PosInfo . Ticket ( ) ;
}
}
}
trade . PositionClose ( ProfitTicket ) ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void MAStopLoss ( )
{
int ProfitTicket ;
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
{
if ( PosInfo . SelectByIndex ( i ) )
{
if ( PosInfo . PositionType ( ) = = POSITION_TYPE_BUY & & PosInfo . PriceOpen ( ) > MAHigh [ 0 ] & & PosInfo . PriceCurrent ( ) < MALow [ 0 ] )
{
ProfitTicket = PosInfo . Ticket ( ) ;
trade . PositionClose ( ProfitTicket ) ;
}
if ( PosInfo . PositionType ( ) = = POSITION_TYPE_SELL & & PosInfo . PriceOpen ( ) < MALow [ 0 ] & & PosInfo . PriceCurrent ( ) > MAHigh [ 0 ] )
{
ProfitTicket = PosInfo . Ticket ( ) ;
trade . PositionClose ( ProfitTicket ) ;
}
}
}
}
///////////////////POSITIONS CHECK/////////////////////////
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool OtherBuyPosition ( string comment )
{
bool other = false ;
for ( int i = PositionsTotal ( ) ; i > = 0 ; i - - )
{
ulong ticket = PositionGetTicket ( i ) ;
if ( PosInfo . SelectByTicket ( ticket ) )
{
double currentPrice = PosInfo . PriceCurrent ( ) ;
double openPrice = PosInfo . PriceOpen ( ) ;
if ( MathAbs ( currentPrice - openPrice ) < Grid_step_buy * _Point & & PosInfo . PositionType ( ) = = POSITION_TYPE_BUY & & ( comment = = PosInfo . Comment ( ) | | comment = = NULL ) )
{
other = true ;
break ;
}
else
{
other = false ;
}
}
}
return other ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool OtherSellPosition ( string comment )
{
bool other = false ;
for ( int i = PositionsTotal ( ) ; i > = 0 ; i - - )
{
ulong ticket = PositionGetTicket ( i ) ;
if ( PosInfo . SelectByTicket ( ticket ) )
{
double currentPrice = PosInfo . PriceCurrent ( ) ;
double openPrice = PosInfo . PriceOpen ( ) ;
if ( MathAbs ( currentPrice - openPrice ) < Grid_step_sell * _Point & & PosInfo . PositionType ( ) = = POSITION_TYPE_SELL & & ( comment = = PosInfo . Comment ( ) | | comment = = NULL ) )
{
other = true ;
break ;
}
else
{
other = false ;
}
}
}
return other ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CloseBuys ( )
{
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
if ( PosInfo . SelectByIndex ( i ) & & PosInfo . PositionType ( ) = = POSITION_TYPE_BUY )
{
double thebuy = PosInfo . PriceOpen ( ) ;
int theBuyTicket = PosInfo . Ticket ( ) ;
trade . PositionClose ( theBuyTicket ) ;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CloseSells ( )
{
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
if ( PosInfo . SelectByIndex ( i ) & & PosInfo . PositionType ( ) = = POSITION_TYPE_SELL )
{
double thesell = PosInfo . PriceOpen ( ) ;
int theSellTicket = PosInfo . Ticket ( ) ;
trade . PositionClose ( theSellTicket ) ;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CloseBuy ( )
{
double Profit ;
int theBuyTicket = PosInfo . Ticket ( ) ;
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
{
if ( PosInfo . SelectByIndex ( i ) & & PosInfo . PositionType ( ) = = POSITION_TYPE_BUY )
{
if ( Profit > PosInfo . Profit ( ) )
{
Profit = PosInfo . Profit ( ) ;
theBuyTicket = PosInfo . Ticket ( ) ;
}
}
}
trade . PositionClose ( theBuyTicket ) ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CloseSell ( )
{
double Profit ;
int theSellTicket = PosInfo . Ticket ( ) ;
for ( int i = PositionsTotal ( ) - 1 ; i > = 0 ; i - - ) // loop all Open Positions
{
if ( PosInfo . SelectByIndex ( i ) & & PosInfo . PositionType ( ) = = POSITION_TYPE_SELL )
{
if ( Profit > PosInfo . Profit ( ) )
{
Profit = PosInfo . Profit ( ) ;
theSellTicket = PosInfo . Ticket ( ) ;
}
}
}
trade . PositionClose ( theSellTicket ) ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Trailing ( )
{
// if(PositionGetInteger(POSITION_MAGIC) == 444444)//adding magic number, if you want you can delete this if you don't want to use magic number
// {
for ( int i = PositionsTotal ( ) -1 ; i > = 0 ; i - - )
{
// string symbol = PositionGetSymbol(i);
ulong PositionTicket = PositionGetTicket ( i ) ;
long trade_type = PositionGetInteger ( POSITION_TYPE ) ;
if ( trade_type = = 0 ) // && (PositionGetString(POSITION_COMMENT) == "BuyLimit" || PositionGetString(POSITION_COMMENT) == "BuyGrid"))
{
if ( bid > PositionGetDouble ( POSITION_PRICE_OPEN ) + NormalizeDouble ( _Point * Grid , _Digits ) )
{
trade . PositionModify ( PositionTicket , NormalizeDouble ( PositionGetDouble ( POSITION_PRICE_OPEN ) + Grid * _Point , _Digits ) , PositionGetDouble ( POSITION_TP ) ) ;
}
}
if ( trade_type = = 1 ) // && (PositionGetString(POSITION_COMMENT) == "SellLimit"|| PositionGetString(POSITION_COMMENT) == "SellGrid"))
{
if ( ask < PositionGetDouble ( POSITION_PRICE_OPEN ) - NormalizeDouble ( _Point * Grid , _Digits ) )
{
trade . PositionModify ( PositionTicket , NormalizeDouble ( PositionGetDouble ( POSITION_PRICE_OPEN ) - Grid * _Point , _Digits ) , PositionGetDouble ( POSITION_TP ) ) ;
}
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void TPmodify ( )
{
// if(PositionGetInteger(POSITION_MAGIC) == 444444)//adding magic number, if you want you can delete this if you don't want to use magic number
// {
for ( int i = PositionsTotal ( ) -1 ; i > = 0 ; i - - )
{
ulong PositionTicket = PositionGetTicket ( i ) ;
long trade_type = PositionGetInteger ( POSITION_TYPE ) ;
if ( trade_type = = 0 & & PosInfo . TakeProfit ( ) ! = meanEntryPriceBuy ( ) + TakeProfitFactor * Grid * _Point & & BuyPositionsCount ( ) > PositionsThreshold )
{
trade . PositionModify ( PositionTicket , PositionGetDouble ( POSITION_SL ) , PositionGetDouble ( POSITION_PRICE_OPEN ) + TakeProfitFactor * Grid * _Point ) ;
if ( PosInfo . PriceCurrent ( ) > meanEntryPriceBuy ( ) + Grid * _Point )
CloseBuys ( ) ;
}
if ( trade_type = = 1 & & PosInfo . TakeProfit ( ) ! = meanEntryPriceSell ( ) - TakeProfitFactor * Grid * _Point & & SellPositionsCount ( ) > PositionsThreshold )
{
trade . PositionModify ( PositionTicket , PositionGetDouble ( POSITION_SL ) , PositionGetDouble ( POSITION_PRICE_OPEN ) - TakeProfitFactor * Grid * _Point ) ;
if ( PosInfo . PriceCurrent ( ) < meanEntryPriceSell ( ) - Grid * _Point )
CloseSells ( ) ;
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void breakEven ( )
{
for ( int i = PositionsTotal ( ) -1 ; i > = 0 ; i - - )
{
double meanEntryBuy = meanEntryPriceBuy ( ) ;
double meanEntrySell = meanEntryPriceSell ( ) ;
ulong PositionTicket = PositionGetTicket ( i ) ;
long trade_type = PositionGetInteger ( POSITION_TYPE ) ;
if ( trade_type = = 0 )
if ( meanEntryBuy < ask - Grid * _Point & & ( PosInfo . StopLoss ( ) < meanEntryBuy | | PosInfo . StopLoss ( ) = = 0 ) )
{
trade . PositionModify ( PositionTicket , meanEntryBuy + 150 * _Point , PositionGetDouble ( POSITION_TP ) ) ;
}
if ( trade_type = = 1 )
if ( meanEntrySell > bid + Grid * _Point & & ( PosInfo . StopLoss ( ) > meanEntrySell | | PosInfo . StopLoss ( ) = = 0 ) )
{
trade . PositionModify ( PositionTicket , meanEntrySell - 150 * _Point , PositionGetDouble ( POSITION_TP ) ) ;
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void slStepUp ( )
{
for ( int i = PositionsTotal ( ) -1 ; i > = 0 ; i - - )
{
ulong PositionTicket = PositionGetTicket ( i ) ;
long trade_type = PositionGetInteger ( POSITION_TYPE ) ;
if ( trade_type = = 0 & & PosInfo . StopLoss ( ) > PosInfo . PriceOpen ( ) ) // && (PositionGetString(POSITION_COMMENT) == "BuyLimit" || PositionGetString(POSITION_COMMENT) == "BuyGrid"))
{
trade . PositionModify ( PositionTicket , NormalizeDouble ( PositionGetDouble ( POSITION_SL ) + Grid * _Point , _Digits ) , PositionGetDouble ( POSITION_TP ) ) ;
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void slStepDown ( )
{
for ( int i = PositionsTotal ( ) -1 ; i > = 0 ; i - - )
{
ulong PositionTicket = PositionGetTicket ( i ) ;
long trade_type = PositionGetInteger ( POSITION_TYPE ) ;
if ( trade_type = = 1 & & PosInfo . StopLoss ( ) < PosInfo . PriceOpen ( ) ) // && (PositionGetString(POSITION_COMMENT) == "BuyLimit" || PositionGetString(POSITION_COMMENT) == "BuyGrid"))
{
trade . PositionModify ( PositionTicket , NormalizeDouble ( PositionGetDouble ( POSITION_SL ) - Grid * _Point , _Digits ) , PositionGetDouble ( POSITION_TP ) ) ;
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void StoplossUpdate ( string comment )
{
int buyCount = BuyPositionsCount ( ) ;
int sellCount = SellPositionsCount ( ) ;
2026-01-12 09:52:32 +03:00
double meanEntryBuy = meanEntryPrice ( " Buy " ) ;
double meanEntrySell = meanEntryPrice ( " Sell " ) ;
2026-01-02 15:37:26 +03:00
for ( int i = PositionsTotal ( ) -1 ; i > = 0 ; i - - )
{
ulong PositionTicket = PositionGetTicket ( i ) ;
long trade_type = PositionGetInteger ( POSITION_TYPE ) ;
2026-01-12 09:52:32 +03:00
if ( trade_type = = POSITION_TYPE_BUY & & comment = = " buy " )
2026-01-02 15:37:26 +03:00
{
2026-01-12 09:52:32 +03:00
double newStopLoss ;
2026-01-02 15:37:26 +03:00
if ( ask < meanEntryBuy + TakeProfitFactor * Grid * _Point )
newStopLoss = StopLossBuy ;
if ( ask > meanEntryBuy + TakeProfitFactor * Grid * _Point )
newStopLoss = NormalizeDouble ( ( ( ( ask + meanEntryBuy ) / 2 ) + ask ) / 2 , _Digits ) ;
if ( PositionGetDouble ( POSITION_SL ) < newStopLoss )
trade . PositionModify ( PositionTicket , newStopLoss , PositionGetDouble ( POSITION_TP ) ) ;
}
2026-01-12 09:52:32 +03:00
if ( trade_type = = POSITION_TYPE_SELL & & comment = = " sell " )
2026-01-02 15:37:26 +03:00
{
2026-01-12 09:52:32 +03:00
double newStopLoss ;
2026-01-02 15:37:26 +03:00
if ( bid > meanEntrySell - TakeProfitFactor * Grid * _Point )
newStopLoss = StopLossSell ;
if ( bid < meanEntrySell - TakeProfitFactor * Grid * _Point )
2026-01-12 09:52:32 +03:00
newStopLoss = NormalizeDouble ( ( ( ( bid + meanEntrySell ) / 2 ) + bid ) / 2 , _Digits ) ;
if ( PositionGetDouble ( POSITION_SL ) > newStopLoss | | PosInfo . StopLoss ( ) = = 0 )
2026-01-02 15:37:26 +03:00
trade . PositionModify ( PositionTicket , newStopLoss , PositionGetDouble ( POSITION_TP ) ) ;
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
string crossOver ( double & Array1 [ ] , double & Array2 [ ] )
{
string crossOver ;
if ( Array1 [ 1 ] > Array2 [ 1 ] & & Array1 [ 2 ] < Array2 [ 2 ] )
{
crossOver = " up " ;
}
if ( Array1 [ 1 ] < Array2 [ 1 ] & & Array1 [ 2 ] > Array2 [ 2 ] )
{
crossOver = " down " ;
}
else
{
crossOver = NULL ;
}
return ( crossOver ) ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int BuyPositionsCount ( )
{
int Buys = 0 ;
for ( int i = PositionsTotal ( ) -1 ; i > = 0 ; i - - )
{
PositionGetTicket ( i ) ;
if ( PositionGetInteger ( POSITION_TYPE ) = = POSITION_TYPE_BUY & & PositionGetString ( POSITION_SYMBOL ) = = _Symbol )
{
Buys = Buys + 1 ;
}
}
return Buys ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int SellPositionsCount ( )
{
int Sells = 0 ;
for ( int i = PositionsTotal ( ) -1 ; i > = 0 ; i - - )
{
PositionGetTicket ( i ) ;
if ( PositionGetInteger ( POSITION_TYPE ) = = POSITION_TYPE_SELL & & PositionGetString ( POSITION_SYMBOL ) = = _Symbol )
{
Sells = Sells + 1 ;
}
}
return Sells ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void SLmodify ( )
{
// if(PositionGetInteger(POSITION_MAGIC) == 444444)//adding magic number, if you want you can delete this if you don't want to use magic number
// {
for ( int i = PositionsTotal ( ) -1 ; i > = 0 ; i - - )
{
ulong PositionTicket = PositionGetTicket ( i ) ;
long trade_type = PositionGetInteger ( POSITION_TYPE ) ;
if ( trade_type = = 0
& & PosInfo . PriceCurrent ( ) > meanEntryPriceBuy ( ) + ( 0.5 * Grid * _Point )
& & ( PositionGetDouble ( POSITION_SL ) < PosInfo . PriceCurrent ( ) - ( ( LowestBuy ( ) + 0.5 * Grid * _Point ) - meanEntryPriceBuy ( ) ) | | PositionGetDouble ( POSITION_SL ) = = 0 ) )
{
trade . PositionModify ( PositionTicket , PosInfo . PriceCurrent ( ) - ( ( LowestBuy ( ) + 0.5 * Grid * _Point ) - meanEntryPriceBuy ( ) ) , PositionGetDouble ( POSITION_TP ) ) ;
Print ( " Lowest buy: " + LowestBuy ( ) ) ;
}
if ( trade_type = = 1
& & PosInfo . PriceCurrent ( ) < meanEntryPriceSell ( ) - ( 0.5 * Grid * _Point )
& & ( PositionGetDouble ( POSITION_SL ) > PosInfo . PriceCurrent ( ) - ( ( HighestSell ( ) - 0.5 * Grid * _Point ) - meanEntryPriceSell ( ) ) | | PositionGetDouble ( POSITION_SL ) = = 0 ) )
{
trade . PositionModify ( PositionTicket , PosInfo . PriceCurrent ( ) - ( ( HighestSell ( ) - 0.5 * Grid * _Point ) - meanEntryPriceSell ( ) ) , PositionGetDouble ( POSITION_TP ) ) ;
Print ( " highest sell: " + HighestSell ( ) ) ;
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double meanEntryPriceBuy ( )
{
double price = 0 ;
double volume = 0 ;
double entry ;
for ( int i = PositionsTotal ( ) -1 ; i > = 0 ; i - - )
{
PositionGetTicket ( i ) ;
if ( PositionGetInteger ( POSITION_TYPE ) = = POSITION_TYPE_BUY & & PositionGetString ( POSITION_SYMBOL ) = = _Symbol )
{
price = price + PosInfo . Volume ( ) * PosInfo . PriceOpen ( ) ;
}
}
for ( int i = PositionsTotal ( ) -1 ; i > = 0 ; i - - )
{
PositionGetTicket ( i ) ;
if ( PositionGetInteger ( POSITION_TYPE ) = = POSITION_TYPE_BUY & & PositionGetString ( POSITION_SYMBOL ) = = _Symbol )
{
volume = volume + PosInfo . Volume ( ) ;
}
}
entry = price / volume ;
return entry ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double meanEntryPriceSell ( )
{
double price = 0 ;
double volume = 0 ;
double entry ;
for ( int i = PositionsTotal ( ) -1 ; i > = 0 ; i - - )
{
PositionGetTicket ( i ) ;
if ( PositionGetInteger ( POSITION_TYPE ) = = POSITION_TYPE_SELL & & PositionGetString ( POSITION_SYMBOL ) = = _Symbol )
{
price = price + PosInfo . Volume ( ) * PosInfo . PriceOpen ( ) ;
}
}
for ( int i = PositionsTotal ( ) -1 ; i > = 0 ; i - - )
{
PositionGetTicket ( i ) ;
if ( PositionGetInteger ( POSITION_TYPE ) = = POSITION_TYPE_SELL & & PositionGetString ( POSITION_SYMBOL ) = = _Symbol )
{
volume = volume + PosInfo . Volume ( ) ;
}
}
entry = price / volume ;
return entry ;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+