Vizion-Trading-EA/Experts/profittrader.mq5

768 lines
49 KiB
MQL5
Raw Permalink Normal View History

<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| QuarterTheory_FINAL_RR.mq5 |
//| 1:5 RR Fib-Based SL/TP + 25% Partials + Trend Reversal |
//| BE at 300pts | Trail 500pts | Close Opposites |
//+------------------------------------------------------------------+
#property copyright "Final Risk-Reward System"
#property version "15.00"
#property strict
#include <Trade/Trade.mqh>
CTrade Trade;
//================ INPUT PARAMETERS ==================//
input group "=== GENERAL ==="
input int MagicNumber = 456789;
input double Risk_Per_Trade = 1.2;
input int Min_Active_Entries = 8;
input int Max_Simultaneous_Trades = 20;
input group "=== MA TREND BIAS (PRIMARY!) ==="
input int MA_1 = 7;
input int MA_2 = 14;
input int MA_3 = 21;
input int MA_4 = 50;
input int MA_5 = 140;
input int MA_6 = 230;
input int MA_7 = 500;
input int MA_8 = 1000;
input int MA_9 = 1100;
input int MA_10 = 1300;
input bool Require_MA_Trend_Bias = true;
input int Min_MA7_Crosses = 2;
input group "=== STOCHASTIC (SECONDARY) ==="
input int Stoch_K_Period = 5;
input int Stoch_D_Period = 3;
input int Stoch_Slowing = 3;
input double Stoch_Overbought = 80.0;
input double Stoch_Oversold = 20.0;
input bool Use_Stoch_Confirmation = true;
input group "=== HIGHER MA RE-ENTRY ==="
input bool ReEnter_At_MA50 = true;
input bool ReEnter_At_MA140 = true;
input bool ReEnter_At_MA230 = true;
input bool ReEnter_At_MA500 = true;
input int MA_Touch_Buffer = 30;
input group "=== FIBONACCI LEVELS ==="
input int Lookback_Bars = 200;
input bool Show_Levels = true;
input group "=== RISK MANAGEMENT ==="
input int Minimum_TP_Points = 3000; // MINIMUM 3000 points TP guaranteed
input bool Use_Fib_Based_SL = true; // Use nearest Fib for SL
input int Max_SL_Points = 1000; // Max SL if Fib too far
input int Move_BE_At_Points = 300; // Move to BE
input int Trailing_SL_Points = 500; // Trailing distance
input double Partial_TP_Percent = 25.0; // Close 25% per hit
input group "=== DAILY LIMITS ==="
input double Max_Daily_Loss_Percent = 5.0;
input double Max_Daily_Profit_Percent = 30.0;
input int Max_Trades_Per_Day = 40;
//================ GLOBALS ==================//
int Stoch_Handle;
double Stoch_K_Current = 0;
double Stoch_K_Previous = 0;
double PriceLevels[];
string LevelTypes[];
int TotalLevels = 0;
int MA_Handles[10];
double MA_Current[10];
double MA_Previous[10];
bool Current_Trend_Bullish = false;
bool Current_Trend_Bearish = false;
bool Previous_Trend_Bullish = false;
bool Previous_Trend_Bearish = false;
datetime Last_Trend_Check = 0;
struct Position
{
ulong ticket;
double entry;
double sl_level;
double tp_level;
double original_lot;
bool is_buy;
bool be_set;
int partials_closed;
};
Position OpenPositions[];
double DailyStart = 0;
int TodayTrades = 0;
datetime LastDay = 0;
//+------------------------------------------------------------------+
int OnInit()
{
Print("========================================");
Print("FINAL RR SYSTEM v15.0");
Print("MINIMUM 3000 POINTS TP GUARANTEED");
Print("Fib-Based SL | 25% Partials");
Print("========================================");
Trade.SetExpertMagicNumber(MagicNumber);
Trade.SetDeviationInPoints(50);
Stoch_Handle = iStochastic(_Symbol, PERIOD_CURRENT, Stoch_K_Period, Stoch_D_Period,
Stoch_Slowing, MODE_SMA, STO_LOWHIGH);
if(Stoch_Handle == INVALID_HANDLE)
{
Print("ERROR: Stochastic failed");
return INIT_FAILED;
}
int periods[10] = {MA_1, MA_2, MA_3, MA_4, MA_5, MA_6, MA_7, MA_8, MA_9, MA_10};
for(int i=0; i<10; i++)
{
MA_Handles[i] = iMA(_Symbol, PERIOD_CURRENT, periods[i], 0, MODE_EMA, PRICE_CLOSE);
if(MA_Handles[i] == INVALID_HANDLE)
{
Print("ERROR: MA ", periods[i], " failed");
return INIT_FAILED;
}
}
CalculatePriceLevels();
if(Show_Levels) DrawLevels();
DailyStart = AccountInfoDouble(ACCOUNT_BALANCE);
Print("Minimum TP: ", Minimum_TP_Points, " points (300 pips) GUARANTEED");
Print("Max SL: ", Max_SL_Points, " points");
Print("BE at: ", Move_BE_At_Points, " points");
Print("Partial TP: ", Partial_TP_Percent, "% per MA/Fib hit");
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
for(int i=0; i<10; i++)
if(MA_Handles[i] != INVALID_HANDLE)
IndicatorRelease(MA_Handles[i]);
if(Stoch_Handle != INVALID_HANDLE)
IndicatorRelease(Stoch_Handle);
ObjectsDeleteAll(0, "Level_");
ObjectsDeleteAll(0, "Arrow_");
ObjectsDeleteAll(0, "TrendLabel");
}
//+------------------------------------------------------------------+
void CalculatePriceLevels()
{
ArrayResize(PriceLevels, 0);
ArrayResize(LevelTypes, 0);
TotalLevels = 0;
double high = iHigh(_Symbol, PERIOD_CURRENT, 0);
double low = iLow(_Symbol, PERIOD_CURRENT, 0);
for(int i=1; i<=Lookback_Bars; i++)
{
double h = iHigh(_Symbol, PERIOD_CURRENT, i);
double l = iLow(_Symbol, PERIOD_CURRENT, i);
if(h > high) high = h;
if(l < low) low = l;
}
double range = high - low;
int size = 0;
ArrayResize(PriceLevels, 10);
ArrayResize(LevelTypes, 10);
PriceLevels[size] = low; LevelTypes[size] = "FIB_0.0"; size++;
PriceLevels[size] = low + range * 0.236; LevelTypes[size] = "FIB_0.236"; size++;
PriceLevels[size] = low + range * 0.382; LevelTypes[size] = "FIB_0.382"; size++;
PriceLevels[size] = low + range * 0.5; LevelTypes[size] = "FIB_0.5"; size++;
PriceLevels[size] = low + range * 0.618; LevelTypes[size] = "FIB_0.618"; size++;
PriceLevels[size] = low + range * 0.786; LevelTypes[size] = "FIB_0.786"; size++;
PriceLevels[size] = high; LevelTypes[size] = "FIB_1.0"; size++;
TotalLevels = size;
}
void DrawLevels()
{
ObjectsDeleteAll(0, "Level_");
for(int i=0; i<TotalLevels; i++)
{
string name = "Level_" + IntegerToString(i);
ObjectCreate(0, name, OBJ_HLINE, 0, 0, PriceLevels[i]);
ObjectSetInteger(0, name, OBJPROP_COLOR, clrDodgerBlue);
ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_DOT);
ObjectSetInteger(0, name, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, name, OBJPROP_BACK, true);
ObjectSetString(0, name, OBJPROP_TEXT, LevelTypes[i]);
}
}
//+------------------------------------------------------------------+
void UpdateMAs()
{
for(int i=0; i<10; i++)
{
double curr[1], prev[1];
if(CopyBuffer(MA_Handles[i], 0, 0, 1, curr) > 0)
MA_Current[i] = curr[0];
if(CopyBuffer(MA_Handles[i], 0, 1, 1, prev) > 0)
MA_Previous[i] = prev[0];
}
}
void UpdateStochastic()
{
double k_curr[1], k_prev[1];
if(CopyBuffer(Stoch_Handle, MAIN_LINE, 0, 1, k_curr) > 0)
Stoch_K_Current = k_curr[0];
if(CopyBuffer(Stoch_Handle, MAIN_LINE, 1, 1, k_prev) > 0)
Stoch_K_Previous = k_prev[0];
}
//+------------------------------------------------------------------+
//| FIND NEAREST FIB LEVEL
//+------------------------------------------------------------------+
double FindNearestFibLevel(double price, bool find_below)
{
double nearest = 0;
double min_distance = 999999;
for(int i=0; i<TotalLevels; i++)
{
double level = PriceLevels[i];
double distance = MathAbs(price - level);
if(find_below && level < price && distance < min_distance)
{
nearest = level;
min_distance = distance;
}
else if(!find_below && level > price && distance < min_distance)
{
nearest = level;
min_distance = distance;
}
}
return nearest;
}
//+------------------------------------------------------------------+
//| CALCULATE DYNAMIC SL/TP - GUARANTEE 3000 POINTS TP
//+------------------------------------------------------------------+
void CalculateDynamicSLTP(double entry, bool is_buy, double &sl, double &tp)
{
// STEP 1: Find SL (nearest Fib or max SL)
if(Use_Fib_Based_SL && TotalLevels > 0)
{
sl = FindNearestFibLevel(entry, is_buy);
// Check if Fib SL is reasonable
if(sl != 0)
{
double fib_sl_distance = MathAbs(entry - sl);
// If Fib SL too far (> max), use max SL
if(fib_sl_distance / _Point > Max_SL_Points)
{
sl = is_buy ? entry - Max_SL_Points * _Point : entry + Max_SL_Points * _Point;
Print("Fib SL too far, using Max SL: ", Max_SL_Points, " points");
}
// If Fib SL too close (< 50), use 800 points
if(fib_sl_distance / _Point < 50)
{
sl = is_buy ? entry - 800 * _Point : entry + 800 * _Point;
Print("Fib SL too close, using 800 points");
}
}
else
{
// No Fib found, use default
sl = is_buy ? entry - 800 * _Point : entry + 800 * _Point;
}
}
else
{
// Fixed SL
sl = is_buy ? entry - 800 * _Point : entry + 800 * _Point;
}
// STEP 2: Set TP to MINIMUM 3000 points
tp = is_buy ? entry + Minimum_TP_Points * _Point
: entry - Minimum_TP_Points * _Point;
// STEP 3: Adjust TP to nearest Fib if it's beyond minimum
double nearest_tp_fib = FindNearestFibLevel(entry, !is_buy);
if(nearest_tp_fib != 0)
{
double fib_tp_distance = MathAbs(nearest_tp_fib - entry);
// If Fib TP is >= 3000 points, use it
if(fib_tp_distance / _Point >= Minimum_TP_Points)
{
tp = nearest_tp_fib;
Print("Using Fib TP: ", (int)(fib_tp_distance/_Point), " points");
}
}
double sl_dist = MathAbs(entry - sl) / _Point;
double tp_dist = MathAbs(tp - entry) / _Point;
double actual_rr = tp_dist / sl_dist;
Print("P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%");
Print("Entry: ", entry);
Print("SL: ", sl, " (", (int)sl_dist, " points)");
Print("TP: ", tp, " (", (int)tp_dist, " points)");
Print("Actual RR: 1:", DoubleToString(actual_rr, 1));
Print("P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%");
}
//+------------------------------------------------------------------+
void DetermineTrendBias()
{
UpdateMAs();
Previous_Trend_Bullish = Current_Trend_Bullish;
Previous_Trend_Bearish = Current_Trend_Bearish;
int bullish_alignment = 0;
int bearish_alignment = 0;
for(int i=0; i<6; i++)
{
if(i < 5 && MA_Current[i] > MA_Current[i+1])
bullish_alignment++;
if(i < 5 && MA_Current[i] < MA_Current[i+1])
bearish_alignment++;
}
bool ma7_above_ma50 = MA_Current[0] > MA_Current[3];
bool ma7_below_ma50 = MA_Current[0] < MA_Current[3];
if(bullish_alignment >= 3 && ma7_above_ma50)
{
Current_Trend_Bullish = true;
Current_Trend_Bearish = false;
}
else if(bearish_alignment >= 3 && ma7_below_ma50)
{
Current_Trend_Bullish = false;
Current_Trend_Bearish = true;
}
ObjectDelete(0, "TrendLabel");
ObjectCreate(0, "TrendLabel", OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, "TrendLabel", OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, "TrendLabel", OBJPROP_XDISTANCE, 10);
ObjectSetInteger(0, "TrendLabel", OBJPROP_YDISTANCE, 30);
if(Current_Trend_Bullish)
{
ObjectSetString(0, "TrendLabel", OBJPROP_TEXT, "TREND: BULLISH <00>!");
ObjectSetInteger(0, "TrendLabel", OBJPROP_COLOR, clrLime);
}
else if(Current_Trend_Bearish)
{
ObjectSetString(0, "TrendLabel", OBJPROP_TEXT, "TREND: BEARISH <00>!");
ObjectSetInteger(0, "TrendLabel", OBJPROP_COLOR, clrRed);
}
else
{
ObjectSetString(0, "TrendLabel", OBJPROP_TEXT, "TREND: RANGING");
ObjectSetInteger(0, "TrendLabel", OBJPROP_COLOR, clrYellow);
}
ObjectSetInteger(0, "TrendLabel", OBJPROP_FONTSIZE, 12);
}
//+------------------------------------------------------------------+
bool TrendReversed()
{
if(Previous_Trend_Bullish && Current_Trend_Bearish)
{
Print("===== TREND REVERSAL: BULL <00>! BEAR =====");
return true;
}
if(Previous_Trend_Bearish && Current_Trend_Bullish)
{
Print("===== TREND REVERSAL: BEAR <00>! BULL =====");
return true;
}
return false;
}
//+------------------------------------------------------------------+
void CloseOppositeTrades(bool close_buys)
{
int closed = 0;
for(int i=PositionsTotal()-1; i>=0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue;
ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
if((close_buys && type == POSITION_TYPE_BUY) ||
(!close_buys && type == POSITION_TYPE_SELL))
{
Trade.PositionClose(ticket);
closed++;
}
}
if(closed > 0)
Print("Closed ", closed, " opposite trades on reversal");
}
//+------------------------------------------------------------------+
int CountMA7Crosses(bool check_bullish)
{
int crosses = 0;
for(int i=1; i<6; i++)
{
if(check_bullish && MA_Current[0] > MA_Current[i])
crosses++;
else if(!check_bullish && MA_Current[0] < MA_Current[i])
crosses++;
}
return crosses;
}
//+------------------------------------------------------------------+
bool IsPriceAtHigherMA(double price, int &ma_index, string &ma_name)
{
double buffer = MA_Touch_Buffer * _Point;
int higher_mas[4] = {3, 4, 5, 6};
string ma_names[4] = {"MA 50", "MA 140", "MA 230", "MA 500"};
for(int i=0; i<4; i++)
{
int idx = higher_mas[i];
if(MathAbs(price - MA_Current[idx]) <= buffer)
{
ma_index = idx;
ma_name = ma_names[i];
return true;
}
}
return false;
}
//+------------------------------------------------------------------+
bool StochConfirms(bool check_bullish)
{
if(!Use_Stoch_Confirmation) return true;
if(check_bullish)
return (Stoch_K_Current < 70 && Stoch_K_Current >= Stoch_K_Previous);
else
return (Stoch_K_Current > 30 && Stoch_K_Current <= Stoch_K_Previous);
}
//+------------------------------------------------------------------+
double GetLotSize(int sl_points)
{
double risk = AccountInfoDouble(ACCOUNT_BALANCE) * Risk_Per_Trade / 100.0;
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
double lot = risk / ((sl_points * _Point / tickSize) * tickValue);
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
lot = MathMax(lot, minLot);
lot = MathMin(lot, maxLot);
lot = NormalizeDouble(lot / step, 0) * step;
return lot;
}
//+------------------------------------------------------------------+
bool CheckLimits()
{
MqlDateTime dt;
TimeCurrent(dt);
dt.hour = 0; dt.min = 0; dt.sec = 0;
datetime today = StructToTime(dt);
if(today != LastDay)
{
DailyStart = AccountInfoDouble(ACCOUNT_BALANCE);
TodayTrades = 0;
LastDay = today;
}
if(TodayTrades >= Max_Trades_Per_Day) return false;
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
double pl = ((balance - DailyStart) / DailyStart) * 100.0;
if(pl <= -Max_Daily_Loss_Percent || pl >= Max_Daily_Profit_Percent)
return false;
return true;
}
//+------------------------------------------------------------------+
void OpenTrade(bool buy, double price, string reason)
{
double sl, tp;
CalculateDynamicSLTP(price, buy, sl, tp);
int sl_points = (int)(MathAbs(price - sl) / _Point);
double lot = GetLotSize(sl_points);
if(lot < SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN)) return;
string comment = (buy ? "BULL" : "BEAR") + " | " + reason;
bool result = buy ? Trade.Buy(lot, _Symbol, price, sl, tp, comment)
: Trade.Sell(lot, _Symbol, price, sl, tp, comment);
if(result)
{
TodayTrades++;
ulong ticket = Trade.ResultOrder();
int size = ArraySize(OpenPositions);
ArrayResize(OpenPositions, size+1);
OpenPositions[size].ticket = ticket;
OpenPositions[size].entry = price;
OpenPositions[size].sl_level = sl;
OpenPositions[size].tp_level = tp;
OpenPositions[size].original_lot = lot;
OpenPositions[size].is_buy = buy;
OpenPositions[size].be_set = false;
OpenPositions[size].partials_closed = 0;
Print("========== TRADE ", TodayTrades, " ==========");
Print(buy ? "BUY" : "SELL", " @ ", price);
Print("Reason: ", reason);
Print("===================================");
string arrow_name = "Arrow_" + IntegerToString(ticket);
ObjectCreate(0, arrow_name, OBJ_ARROW, 0, TimeCurrent(), price);
ObjectSetInteger(0, arrow_name, OBJPROP_COLOR, buy ? clrLime : clrRed);
ObjectSetInteger(0, arrow_name, OBJPROP_ARROWCODE, buy ? 233 : 234);
ObjectSetInteger(0, arrow_name, OBJPROP_WIDTH, 3);
}
}
//+------------------------------------------------------------------+
void ManagePositions()
{
UpdateMAs();
for(int i=PositionsTotal()-1; i>=0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue;
int idx = -1;
for(int j=0; j<ArraySize(OpenPositions); j++)
{
if(OpenPositions[j].ticket == ticket)
{
idx = j;
break;
}
}
if(idx == -1) continue;
double entry = OpenPositions[idx].entry;
double sl = PositionGetDouble(POSITION_SL);
bool is_buy = OpenPositions[idx].is_buy;
double current = is_buy ? SymbolInfoDouble(_Symbol, SYMBOL_BID)
: SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double profit_points = is_buy ? (current - entry) / _Point
: (entry - current) / _Point;
// Move to BE at 300 points
if(!OpenPositions[idx].be_set && profit_points >= Move_BE_At_Points)
{
if((is_buy && sl < entry) || (!is_buy && sl > entry))
{
Trade.PositionModify(ticket, entry, 0);
OpenPositions[idx].be_set = true;
Print("BE SET: ", ticket, " @ ", entry);
}
}
// 25% Partial TPs at MA 50, 140, 230, 500
double lot = PositionGetDouble(POSITION_VOLUME);
// Check if at MA levels and close 25%
int ma_hit_idx = -1;
string ma_hit_name = "";
if(IsPriceAtHigherMA(current, ma_hit_idx, ma_hit_name))
{
if(OpenPositions[idx].partials_closed < 4)
{
double close_size = NormalizeDouble(OpenPositions[idx].original_lot * Partial_TP_Percent / 100.0, 2);
if(close_size > 0 && close_size <= lot)
{
Trade.PositionClosePartial(ticket, close_size);
OpenPositions[idx].partials_closed++;
Print("PARTIAL TP ", OpenPositions[idx].partials_closed, ": ", ma_hit_name,
" | Closed ", Partial_TP_Percent, "%");
}
}
}
// Trailing SL by 500 points
if(profit_points >= Trailing_SL_Points + 100)
{
double newSL = is_buy ? current - Trailing_SL_Points * _Point
: current + Trailing_SL_Points * _Point;
if((is_buy && newSL > sl + 50 * _Point) ||
(!is_buy && newSL < sl - 50 * _Point))
{
Trade.PositionModify(ticket, newSL, 0);
}
}
}
}
//+------------------------------------------------------------------+
void OnTick()
{
if(TimeCurrent() - Last_Trend_Check >= 5)
{
DetermineTrendBias();
if(TrendReversed())
{
if(Current_Trend_Bullish)
CloseOppositeTrades(false); // Close sells
else if(Current_Trend_Bearish)
CloseOppositeTrades(true); // Close buys
}
Last_Trend_Check = TimeCurrent();
}
ManagePositions();
if(!CheckLimits()) return;
int buy_count = 0;
int sell_count = 0;
for(int i=0; i<PositionsTotal(); i++)
{
if(PositionGetTicket(i) == 0) continue;
if(PositionGetString(POSITION_SYMBOL) == _Symbol &&
PositionGetInteger(POSITION_MAGIC) == MagicNumber)
{
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
buy_count++;
else
sell_count++;
}
}
int total_open = buy_count + sell_count;
if(total_open >= Max_Simultaneous_Trades) return;
bool force_entry = (total_open < Min_Active_Entries);
static datetime last_calc = 0;
if(TimeCurrent() - last_calc > 1800)
{
CalculatePriceLevels();
if(Show_Levels) DrawLevels();
last_calc = TimeCurrent();
}
UpdateMAs();
UpdateStochastic();
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double current = (bid + ask) / 2;
int ma7_crosses_bull = CountMA7Crosses(true);
int ma7_crosses_bear = CountMA7Crosses(false);
int higher_ma_idx = -1;
string ma_name = "";
bool at_higher_ma = IsPriceAtHigherMA(current, higher_ma_idx, ma_name);
// BUY ONLY IF BULLISH
if(Current_Trend_Bullish || force_entry)
{
bool buy_signal = false;
string buy_reason = "";
if(ma7_crosses_bull >= Min_MA7_Crosses && StochConfirms(true))
{
buy_signal = true;
buy_reason = "MA7 " + IntegerToString(ma7_crosses_bull) + "x + Stoch";
}
if(at_higher_ma && ma7_crosses_bull >= 1 && StochConfirms(true))
{
buy_signal = true;
buy_reason = ma_name + " TOUCH";
}
if(force_entry && ma7_crosses_bull >= 1 && buy_count < sell_count)
{
buy_signal = true;
buy_reason = "FORCE (" + IntegerToString(total_open) + "/" + IntegerToString(Min_Active_Entries) + ")";
}
if(buy_signal)
OpenTrade(true, ask, buy_reason);
}
// SELL ONLY IF BEARISH
if(Current_Trend_Bearish || force_entry)
{
bool sell_signal = false;
string sell_reason = "";
if(ma7_crosses_bear >= Min_MA7_Crosses && StochConfirms(false))
{
sell_signal = true;
sell_reason = "MA7 " + IntegerToString(ma7_crosses_bear) + "x + Stoch";
}
if(at_higher_ma && ma7_crosses_bear >= 1 && StochConfirms(false))
{
sell_signal = true;
sell_reason = ma_name + " TOUCH";
}
if(force_entry && ma7_crosses_bear >= 1 && sell_count < buy_count)
{
sell_signal = true;
sell_reason = "FORCE (" + IntegerToString(total_open) + "/" + IntegerToString(Min_Active_Entries) + ")";
}
if(sell_signal)
OpenTrade(false, bid, sell_reason);
}
}
//+------------------------------------------------------------------+