#property strict #include #include extern string midasama = "MIDASAMA TRADER EA, www.midasama-trader.com "; extern int MagicOne = 11; extern int MagicTwo = 22; extern int StartHour = 0; extern int EndHour = 24; extern bool USE_MARKET_ORDERS = false; extern bool USE_STOP_ORDERS = true; extern bool USE_LIMIT_ORDERS = false; extern int Candle_Analisis = 7; extern int Time_life_hours_stop = 244; extern int Time_life_hours_limit = 244; extern int TimeCandle = 240; extern int Delta = 40; extern int DeltaStop = 40; extern int DeltaLimit = 40; extern double PercentProfit = 0.3; extern string cl = "==== Close Orders ===="; extern bool Close_Revers_Signal = false; extern int TakeProfit = 0; extern int StopLoss = 0; extern int TrailingStart = 7; extern int TrailingStop = 2; extern int TrailingStep = 1; extern string mm = "=== Money Management ==="; extern double plus_Lots = 0.0; extern double Lots = 0.01; extern double RiskPercent = 0.0; extern int MaxOrders = 1; extern string set_tr = "=== Settings trade ==="; extern int Slippage = 7; extern int MaxSpread = 30; extern bool LOGO=true;//Use_LOGO extern double index = 0.3; // Index extern int VolatilityL = 100; // VoL extern int DistanceInPips = 20; // OTL_TS extern int TrailStart=14; // TrallStart extern int TrailStep=8;// TrallStep extern double ManualLotsize = 0.1; // FixedLot extern bool MoneyManagement = True; // Use_AutoMM extern double Risk = 10.0; // AutoMM extern int Magic = 8723; // Magic extern string OrderCmt = "SAFE"; // OpenOrderComment double VolatilityLimit=VolatilityL; ENUM_TIMEFRAMES TimeFrame = PERIOD_CURRENT; int MaxExecution = 0; int MaxExecutionMinutes = 5; double AddPriceGap = 0; int Breakeven = 0; int LockInPips = 0; double Commission = 0; double MinimumUseStopLevel = 0; bool UseDynamicVolatilityLimit = FALSE; double VolatilityMultiplier = 125; bool UseVolatilityPercentage = FALSE; double VolatilityPercentageLimit = 0; int UseIndicatorSwitch = 1; int Indicatorperiod = 3; double BBDeviation = 2.0; double EnvelopesDeviation = 0.07; int OrderExpireSeconds = 3600; double MinLots = 0.01; double MaxLots = 10000.0; double MinMarginLevel = 100; string Configuration = "==== Configuration ===="; bool ReverseTrade = FALSE; // ReverseTrade //. Trade comments that appears in the Trade and Account History tab bool ECN_Mode = FALSE; // ECN Mode //: True for brokers that don't accept SL and TP to be sent at the same time as the order bool Debug = FALSE; // Debug: Print huge log files with info, only for debugging purposes bool Verbose = FALSE; // Verbose: Additional log information printed in the Expert tab //--------------------------- Globals -------------------------------------------------------------- // All globals should here have their name starting with a CAPITAL character // All variables are arranged according to their data type string EA_version = "Safe v1.0"; datetime StartTime; // Initial time datetime LastTime; // For measuring tics int BrokerDigits = 0; // Nnumber of digits that the broker uses for this currency pair int GlobalError = 0; // To keep track on number of added errors int TickCounter = 0; // Counting tics int UpTo30Counter = 0; // For calculating average spread int Execution = -1; // For Execution speed, -1 means no speed int Avg_execution = 0; // Average Execution speed int Execution_samples = 0; // For calculating average Execution speed int Leverage; // Account Leverage in percentage int Err_unchangedvalues; // Error count for unchanged values (modify to the same values) int Err_busyserver; // Error count for busy server int Err_lostconnection; // Error count for lost connection int Err_toomanyrequest; // Error count for too many requests int Err_invalidprice; // Error count for invalid price int Err_invalidstops; // Error count for invalid SL and/or TP int Err_invalidtradevolume;// Error count for invalid lot size int Err_pricechange; // Error count for change of price int Err_brokerbuzy; // Error count for broker is buzy int Err_requotes; // Error count for requotes int Err_toomanyrequests; // Error count for too many requests int Err_trademodifydenied; // Error count for modify orders is denied int Err_tradecontextbuzy; // error count for trade context is buzy int SkippedTicks = 0; // Used for simulation of latency during backtests, how many tics that should be skipped int Ticks_samples = 0; // Used for simulation of latency during backtests, number of tick samples int Tot_closed_pos; // Number of closed positions for this EA int Tot_Orders; // Number of open orders disregarding of magic and pairs int Tot_open_pos; // Number of open positions for this EA double LotBase; // Amount of money in base currency for 1 lot double Tot_open_profit; // A summary of the current open profit/loss for this EA double Tot_open_lots; // A summary of the current open lots for this EA double Tot_open_swap; // A summary of the current charged swaps of the open positions for this EA double Tot_open_commission;// A summary of the currebt charged commission of the open positions for this EA double G_equity; // Current equity for this EA double Changedmargin; // Free margin for this account double Tot_closed_lots; // A summary of the current closed lots for this EA double Tot_closed_profit; // A summary of the current closed profit/loss for this EA double Tot_closed_swap; // A summary of the current closed swaps for this EA double Tot_closed_comm; // A summary of the current closed commission for this EA double G_balance = 0; // Balance for this EA double Array_spread[30]; // Store spreads for the last 30 tics double LotSize; // Lotsize double Highest; // LotSize indicator value double Lowest; // Lowest indicator value double StopLevel; // Broker StopLevel double StopOut; // Broker stoput percentage double LotStep; // Broker LotStep double MarginForOneLot; // Margin required for 1 lot double Avg_tickspermin; // Used for simulation of latency during backtests double MarginFree; // Free margin in percentage double lastbuyprice,lastsellprice; int lastorderbar=0,CBAR; //------------------------- BreakEven Routine update bool dummyResult; double pipMultiplier = 1; double pPoint; string s_symbol; int digit; //======================= Program initialization =================================================== void OnInit() { OrderExpireSeconds=0; s_symbol = Symbol(); pPoint = Point; digit = Digits; if (digit==2 || digit==4) pipMultiplier = 1; if (digit==3 || digit==5) pipMultiplier = 10; if (digit==6) pipMultiplier = 100; // Print short message at the start of initalization Print ("====== Initialization of ", EA_version, " ======"); // If we don't run a backtest if ( IsTesting() == FALSE ) { // Check if timeframe of chart matches timeframe of external setting // if ( Period() != TimeFrame ) // { // The setting of timefram,e does not match the chart tiomeframe, so alert of this and exit // Alert ("The EA has been set to run on timeframe: ", EnumToString( TimeFrame )," but it has been attached to a chart with timeframe: ", Period() ); // ExpertRemove(); // } } // If we have any objects on the screen then clear the screen sub_DeleteDisplay(); // clear the chart // Reset time for Execution control StartTime = TimeLocal(); // Reset error variable GlobalError = -1; // Get the broker decimals BrokerDigits = Digits; // Get Leverage Leverage = AccountLeverage(); // Calculate StopLevel as max of either STOPLEVEL or FREEZELEVEL StopLevel = MathMax ( MarketInfo ( Symbol(), MODE_FREEZELEVEL ), MarketInfo ( Symbol(), MODE_STOPLEVEL ) ); // Then calculate the StopLevel as max of either this StopLevel or MinimumUseStopLevel StopLevel = MathMax ( MinimumUseStopLevel, StopLevel ); // Get stoput level and re-calculate as fraction StopOut = AccountStopoutLevel(); // Calculate LotStep LotStep = MarketInfo ( Symbol(), MODE_LOTSTEP ); // Check to confirm that indicator switch is valid choices, if not force to 1 (Moving Average) if ( UseIndicatorSwitch < 1 || UseIndicatorSwitch > 4 ) UseIndicatorSwitch = 1; // If indicator switch is set to 4, using iATR, tben UseVolatilityPercentage cannot be used, so force it to FALSE if ( UseIndicatorSwitch == 4 ) UseVolatilityPercentage = FALSE; // Adjust SL and TP to broker StopLevel if they are less than this StopLevel StopLoss = int(MathMax ( StopLoss, StopLevel )); //TakeProfit = MathMax ( TakeProfit, StopLevel ); // Re-calculate variables VolatilityPercentageLimit = VolatilityPercentageLimit / 100 + 1; VolatilityMultiplier = VolatilityMultiplier / 10; ArrayInitialize ( Array_spread, 0 ); VolatilityLimit = VolatilityLimit * Point; Commission = sub_normalizebrokerdigits ( Commission * Point ); //TrailingStart = TrailingStart * Point; StopLevel = StopLevel * Point; AddPriceGap = AddPriceGap * Point; // If we have set MaxLot and/or MinLots to more/less than what the broker allows, then adjust accordingly if ( MinLots < MarketInfo ( Symbol(), MODE_MINLOT ) ) MinLots = MarketInfo ( Symbol(), MODE_MINLOT ); if ( MaxLots > MarketInfo ( Symbol(), MODE_MAXLOT ) ) MaxLots = MarketInfo ( Symbol(), MODE_MAXLOT ); if ( MaxLots < MinLots ) MaxLots = MinLots; // Fetch the margin required for 1 lot MarginForOneLot = MarketInfo ( Symbol(), MODE_MARGINREQUIRED ); // Fetch the amount of money in base currency for 1 lot LotBase = MarketInfo ( Symbol(), MODE_LOTSIZE ); // Also make sure that if the risk-percentage is too low or too high, that it's adjusted accordingly //sub_recalculatewrongrisk(); // Calculate intitial LotSize LotSize = sub_calculatelotsize(); // If magic number is set to a value less than 0, then calculate MagicNumber automatically if ( Magic < 0 ) Magic = sub_magicnumber(); // If Execution speed should be measured, then adjust maxexecution from minutes to seconds if ( MaxExecution > 0 ) MaxExecutionMinutes = MaxExecution * 60; // Print initial info sub_printdetails(); // Check through all closed and open orders to get stats sub_CheckThroughAllClosedOrders(); sub_CheckThroughAllOpenOrders(); // Show info in graphics if (LOGO==true) sub_ShowGraphInfo(); // Print short message at the end of initialization Print ( "========== Initialization complete! ===========\n" ); } //======================= Program deinitialization ================================================= void OnDeinit( const int reason ) { string text = ""; // Print summarize of broker errors sub_printsumofbrokererrors(); // Delete all objects on the screen sub_DeleteDisplay(); // Check through all closed orders sub_CheckThroughAllClosedOrders(); // If we're running as backtest, then print some result if ( IsTesting ( ) == TRUE ) { Print ( "Total closed lots = ", DoubleToStr ( Tot_closed_lots, 2 ) ); Print ( "Total closed swap = ", DoubleToStr ( Tot_closed_swap, 2 ) ); Print ( "Total closed commission = ", DoubleToStr ( Tot_closed_comm, 2 ) ); // If we run backtests and simulate latency, then print result if ( MaxExecution > 0 ) { text = text + "During backtesting " + (string) SkippedTicks + " number of ticks was "; text = text + "skipped to simulate latency of up to " + (string) MaxExecution + " ms"; sub_printandcomment ( text ); } } // Print short message when EA has been deinitialized Print ( EA_version, " has been deinitialized!" ); // Print the uninitialization reason code Print ( __FUNCTION__, "_Uninitalization reason code = ", reason ); //--- The second way to get the uninitialization reason code Print ( __FUNCTION__, "_UninitReason = ", sub_UninitReasonText( _UninitReason ) ); } void OnTick() { if (CBAR Indicatorperiod ) { // Call the actual main subroutine if (IsTesting()==false) { //if (OrdersTotal()<1) sub_trade(); //if (OrdersTotal()>0) if (CountTrades()<1) sub_trade(); if (CountTrades()>9 && CountTrades()<106) {CloseThisSymbolAllPending(); TrailingAlls(TrailStart,TrailStep); } } else if (IsTesting()==true) { if (CountTrades()<1) sub_trade(); if (CountTrades()>9 && CountTrades()<106) {CloseThisSymbolAllPending(); TrailingAlls(TrailStart,TrailStep); } } if (Breakeven>0) breakEvenManager(); // Check through all closed and open orders to get stats to show on screen sub_CheckThroughAllClosedOrders(); sub_CheckThroughAllOpenOrders(); if (LOGO==true) sub_ShowGraphInfo(); } // We have not yet enough of bar data, so print message else Print ( "Please wait until enough of bar data has been gathered!" ); } // This is the main trading subroutine void sub_trade() { string textstring; string pair; string indy; datetime orderexpiretime; bool select = FALSE; bool wasordermodified = FALSE; bool ordersenderror = FALSE; bool isbidgreaterthanima = FALSE; bool isbidgreaterthanibands = FALSE; bool isbidgreaterthanenvelopes = FALSE; bool isbidgreaterthanindy = FALSE; int orderticket; int loopcount2; int loopcount1; int pricedirection; int counter1; int counter2; int askpart; int bidpart; double ask; double bid; double askplusdistance; double bidminusdistance; double volatilitypercentage = 0; double orderprice; double orderstoploss; double ordertakeprofit; double ihigh; double ilow; double imalow = 0; double imahigh = 0; double imadiff; double ibandsupper = 0; double ibandslower = 0; double ibandsdiff; double envelopesupper = 0; double envelopeslower = 0; double envelopesdiff; double volatility; double spread; double avgspread; double realavgspread; double fakeprice; double sumofspreads; double askpluscommission; double bidminuscommission; double skipticks; double am = 0.000000001; // Set variable to a very small number double marginlevel; double tmpexecution; ReverseTrade=false; if (lastorderbar= skipticks ) { Execution = -1; SkippedTicks = 0; } else { SkippedTicks ++; } } // Get Ask and Bid for the currency ask = MarketInfo ( Symbol(), MODE_ASK ); bid = MarketInfo ( Symbol(), MODE_BID ); // Calculate the channel of Volatility based on the difference of iHigh and iLow during current bar ihigh = iHigh ( Symbol(), TimeFrame, 0 ); ilow = iLow ( Symbol(), TimeFrame, 0 ); volatility = ihigh - ilow; // Reset printout string indy = ""; // Calculate a channel on Moving Averages, and check if the price is outside of this channel. if ( UseIndicatorSwitch == 1 || UseIndicatorSwitch == 4 ) { HideTestIndicators(true); imalow = iMA ( Symbol(), TimeFrame, Indicatorperiod, 0, MODE_LWMA, PRICE_LOW, 0 ); imahigh = iMA ( Symbol(), TimeFrame, Indicatorperiod, 0, MODE_LWMA, PRICE_HIGH, 0 ); imadiff = imahigh - imalow; isbidgreaterthanima = bid >= imalow + imadiff / 2.0; indy = "iMA_low: " + sub_dbl2strbrokerdigits ( imalow ) + ", iMA_high: " + sub_dbl2strbrokerdigits ( imahigh ) + ", iMA_diff: " + sub_dbl2strbrokerdigits ( imadiff ); HideTestIndicators(false); } // Calculate a channel on BollingerBands, and check if the price is outside of this channel if ( UseIndicatorSwitch == 2 ) { ibandsupper = iBands ( Symbol(), TimeFrame, Indicatorperiod, BBDeviation, 0, PRICE_OPEN, MODE_UPPER, 0 ); ibandslower = iBands ( Symbol(), TimeFrame, Indicatorperiod, BBDeviation, 0, PRICE_OPEN, MODE_LOWER, 0 ); ibandsdiff = ibandsupper - ibandslower; isbidgreaterthanibands = bid >= ibandslower + ibandsdiff / 2.0; indy = "iBands_upper: " + sub_dbl2strbrokerdigits ( ibandsupper ) + ", iBands_lower: " + sub_dbl2strbrokerdigits ( ibandslower ) + ", iBands_diff: " + sub_dbl2strbrokerdigits ( ibandsdiff ); } // Calculate a channel on Envelopes, and check if the price is outside of this channel if ( UseIndicatorSwitch == 3 ) { envelopesupper = iEnvelopes ( Symbol(), TimeFrame, Indicatorperiod, MODE_LWMA, 0, PRICE_OPEN, EnvelopesDeviation, MODE_UPPER, 0 ); envelopeslower = iEnvelopes ( Symbol(), TimeFrame, Indicatorperiod, MODE_LWMA, 0, PRICE_OPEN, EnvelopesDeviation, MODE_LOWER, 0 ); envelopesdiff = envelopesupper - envelopeslower; isbidgreaterthanenvelopes = bid >= envelopeslower + envelopesdiff / 2.0; indy = "iEnvelopes_upper: " + sub_dbl2strbrokerdigits ( envelopesupper ) + ", iEnvelopes_lower: " + sub_dbl2strbrokerdigits ( envelopeslower ) + ", iEnvelopes_diff: " + sub_dbl2strbrokerdigits ( envelopesdiff) ; } // Reset breakout variable as FALSE isbidgreaterthanindy = FALSE; // Reset pricedirection for no indication of trading direction pricedirection = 0; // If we're using iMA as indicator, then set variables from it if ( UseIndicatorSwitch == 1 && isbidgreaterthanima == TRUE ) { isbidgreaterthanindy = TRUE; Highest = imahigh; Lowest = imalow; } // If we're using iBands as indicator, then set variables from it else if ( UseIndicatorSwitch == 2 && isbidgreaterthanibands == TRUE ) { isbidgreaterthanindy = TRUE; Highest = ibandsupper; Lowest = ibandslower; } // If we're using iEnvelopes as indicator, then set variables from it else if ( UseIndicatorSwitch == 3 && isbidgreaterthanenvelopes == TRUE ) { isbidgreaterthanindy = TRUE; Highest = envelopesupper; Lowest = envelopeslower; } // Calculate spread spread = ask - bid; // Calculate lot size LotSize = sub_calculatelotsize(); // calculatwe orderexpiretime, but only if it is set to a value if ( OrderExpireSeconds != 0 ) orderexpiretime = TimeCurrent() + OrderExpireSeconds; else orderexpiretime = 0; // Calculate average true spread, which is the average of the spread for the last 30 tics ArrayCopy ( Array_spread, Array_spread, 0, 1, 29 ); Array_spread[29] = spread; if ( UpTo30Counter < 30 ) UpTo30Counter ++; sumofspreads = 0; loopcount2 = 29; for ( loopcount1 = 0; loopcount1 < UpTo30Counter; loopcount1 ++ ) { sumofspreads += Array_spread[loopcount2]; loopcount2 --; } // Calculate an average of spreads based on the spread from the last 30 tics avgspread = sumofspreads / UpTo30Counter; // Calculate price and spread considering commission askpluscommission = sub_normalizebrokerdigits ( ask + Commission ); bidminuscommission = sub_normalizebrokerdigits ( bid - Commission ); realavgspread = avgspread + Commission; // Recalculate the VolatilityLimit if it's set to dynamic. It's based on the average of spreads multiplied with the VolatilityMulitplier constant if ( UseDynamicVolatilityLimit == TRUE ) VolatilityLimit = realavgspread * VolatilityMultiplier; // If the variables below have values it means that we have enough of data from broker server. if ( volatility && VolatilityLimit && Lowest && Highest && UseIndicatorSwitch != 4 ) { // We have a price breakout, as the Volatility is outside of the VolatilityLimit, so we can now open a trade if ( volatility > VolatilityLimit ) { if (lastbuyprice!=0 && lastorderbar!=10000 && (Ask < lastbuyprice || Bid>lastsellprice)) ReverseTrade=true; // Calculate how much it differs volatilitypercentage = volatility / VolatilityLimit; // In case of UseVolatilityPercentage == TRUE then also check if it differ enough of percentage if ( ( UseVolatilityPercentage == FALSE ) || ( UseVolatilityPercentage == TRUE && volatilitypercentage > VolatilityPercentageLimit ) ) { if ( bid < Lowest ) { if ( ReverseTrade == FALSE ) pricedirection = -1; // BUY or BUYSTOP else // ReverseTrade == true pricedirection = 1; // SELL or SELLSTOP } else if ( bid > Highest ) { if ( ReverseTrade == FALSE ) pricedirection = 1; // SELL or SELLSTOP else // ReverseTrade == true pricedirection = -1; // BUY or BUYSTOP } } } // The Volatility is less than the VolatilityLimit so we set the volatilitypercentage to zero else volatilitypercentage = 0; } // Check for out of money if ( AccountEquity() <= 0.0 ) { Print ( "ERROR -- Account Equity is " + DoubleToStr ( MathRound ( AccountEquity() ), 0 ) ); return; } // Reset Execution time Execution = -1; // Reset counters counter1 = 0; counter2 = 0; // Loop through all open orders (if any) to either modify them or delete them for ( loopcount2 = 0; loopcount2 < OrdersTotal(); loopcount2 ++ ) { // Select an order from the open orders select = OrderSelect ( loopcount2, SELECT_BY_POS, MODE_TRADES ); // We've found an that matches the magic number and is open if ( OrderMagicNumber() == Magic && OrderCloseTime() == 0 ) { // If the order doesn't match the currency pair from the chart then check next open order if ( OrderSymbol() != Symbol() ) { // Increase counter counter2 ++; continue; } // Select order by type of order switch ( OrderType() ) { // We've found a matching BUY-order case OP_BUY: // Start endless loop while ( TRUE ) { // Update prices from the broker RefreshRates(); // Set SL and TP orderstoploss = OrderStopLoss(); ordertakeprofit = OrderTakeProfit(); // Ok to modify the order if its TP is less than the price+commission+StopLevel AND price+StopLevel-TP greater than trailingStart if ( ordertakeprofit < sub_normalizebrokerdigits ( askpluscommission + TakeProfit * Point + AddPriceGap ) && askpluscommission + TakeProfit * Point + AddPriceGap - ordertakeprofit > TrailingStart ) { // Set SL and TP orderstoploss = sub_normalizebrokerdigits ( bid - StopLoss * Point - AddPriceGap ); ordertakeprofit = sub_normalizebrokerdigits ( askpluscommission + TakeProfit * Point + AddPriceGap ); // Send an OrderModify command with adjusted SL and TP if ( orderstoploss != OrderStopLoss() && ordertakeprofit != OrderTakeProfit() ) { // Start Execution timer Execution = (int) GetTickCount(); // Try to modify order wasordermodified = OrderModify ( OrderTicket(), 0, orderstoploss, ordertakeprofit, orderexpiretime, Lime ); } // Order was modified with new SL and TP if ( wasordermodified == TRUE ) { // Calculate Execution speed Execution = (int) GetTickCount() - Execution; // If we have choosen to take snapshots and we're not backtesting, then do so break; } // Order was not modified else { // Reset Execution counter Execution = -1; // Add to errors sub_errormessages(); // Print if debug or verbose if ( Debug || Verbose ) Print ( "Order could not be modified because of ", ErrorDescription ( GetLastError() ) ); // Order has not been modified and it has no StopLoss if ( orderstoploss == 0 ) // Try to modify order with a safe hard SL that is 3 pip from current price wasordermodified = OrderModify ( OrderTicket(), 0, NormalizeDouble ( Bid - 30, BrokerDigits ), 0, 0, Red ); } } // Break out from while-loop since the order now has been modified break; } // count 1 more up counter1 ++; // Break out from switch break; // We've found a matching SELL-order case OP_SELL: // Start endless loop while ( TRUE ) { // Update broker prices RefreshRates(); // Set SL and TP orderstoploss = OrderStopLoss(); ordertakeprofit = OrderTakeProfit(); // Ok to modify the order if its TP is greater than price-commission-StopLevel AND TP-price-commission+StopLevel is greater than trailingstart if ( ordertakeprofit > sub_normalizebrokerdigits ( bidminuscommission - TakeProfit * Point - AddPriceGap ) && ordertakeprofit - bidminuscommission + TakeProfit * Point - AddPriceGap > TrailingStart ) { // set SL and TP orderstoploss = sub_normalizebrokerdigits ( ask + StopLoss * Point + AddPriceGap ); ordertakeprofit = sub_normalizebrokerdigits ( bidminuscommission - TakeProfit * Point - AddPriceGap ); // Send an OrderModify command with adjusted SL and TP if ( orderstoploss != OrderStopLoss() && ordertakeprofit != OrderTakeProfit() ) { // Start Execution timer Execution = (int) GetTickCount(); wasordermodified = OrderModify ( OrderTicket(), 0, orderstoploss, ordertakeprofit, orderexpiretime, Orange ); } // Order was modiified with new SL and TP if ( wasordermodified == TRUE ) { // Calculate Execution speed Execution = (int) GetTickCount() - Execution; // If we have choosen to take snapshots and we're not backtesting, then do so // Break out from while-loop since the order now has been modified break; } // Order was not modified else { // Reset Execution counter Execution = -1; // Add to errors sub_errormessages(); // Print if debug or verbose if ( Debug || Verbose ) Print ( "Order could not be modified because of ", ErrorDescription ( GetLastError() ) ); // Lets wait 1 second before we try to modify the order again Sleep ( 1000 ); // Order has not been modified and it has no StopLoss if ( orderstoploss == 0 ) // Try to modify order with a safe hard SL that is 3 pip from current price wasordermodified = OrderModify ( OrderTicket(), 0, NormalizeDouble ( Ask + 30, BrokerDigits), 0, 0, Red ); } } // Break out from while-loop since the order now has been modified break; } // count 1 more up counter1 ++; // Break out from switch break; // We've found a matching BUYSTOP-order case OP_BUYSTOP: // Price must NOT be larger than indicator in order to modify the order, otherwise the order will be deleted if ( isbidgreaterthanindy == FALSE ) { // Calculate how much Price, SL and TP should be modified orderprice = sub_normalizebrokerdigits ( ask + StopLevel + AddPriceGap ); orderstoploss = sub_normalizebrokerdigits ( orderprice - spread - StopLoss * Point - AddPriceGap ); ordertakeprofit = sub_normalizebrokerdigits ( orderprice + Commission + TakeProfit * Point + AddPriceGap ); // Start endless loop while ( TRUE ) { // Ok to modify the order if price+StopLevel is less than orderprice AND orderprice-price-StopLevel is greater than trailingstart if ( orderprice < OrderOpenPrice() && OrderOpenPrice() - orderprice > TrailingStart ) { // Send an OrderModify command with adjusted Price, SL and TP if ( orderstoploss != OrderStopLoss() && ordertakeprofit != OrderTakeProfit() ) { RefreshRates(); // Start Execution timer Execution = (int) GetTickCount(); wasordermodified = OrderModify ( OrderTicket(), orderprice, orderstoploss, ordertakeprofit, 0, Lime ); } // Order was modified if ( wasordermodified == TRUE ) { // Calculate Execution speed Execution = (int) GetTickCount() - Execution; // Print if debug or verbose if ( Debug || Verbose ) Print ( "Order executed in " + (string) Execution + " ms" ); } // Order was not modified else { // Reset Execution counter Execution = -1; // Add to errors sub_errormessages(); } } // Break out from endless loop break; } // Increase counter counter1 ++; } // Price was larger than the indicator //else // Delete the order // select = OrderDelete ( OrderTicket() ); // Break out from switch break; // We've found a matching SELLSTOP-order case OP_SELLSTOP: // Price must be larger than the indicator in order to modify the order, otherwise the order will be deleted if ( isbidgreaterthanindy == TRUE ) { // Calculate how much Price, SL and TP should be modified orderprice = sub_normalizebrokerdigits ( bid - StopLevel - AddPriceGap ); orderstoploss = sub_normalizebrokerdigits ( orderprice + spread + StopLoss * Point + AddPriceGap ); ordertakeprofit = sub_normalizebrokerdigits ( orderprice - Commission - TakeProfit * Point - AddPriceGap ); // Endless loop while ( TRUE ) { // Ok to modify order if price-StopLevel is greater than orderprice AND price-StopLevel-orderprice is greater than trailingstart if ( orderprice > OrderOpenPrice() && orderprice - OrderOpenPrice() > TrailingStart) { // Send an OrderModify command with adjusted Price, SL and TP if ( orderstoploss != OrderStopLoss() && ordertakeprofit != OrderTakeProfit() ) { RefreshRates(); // Start Execution counter Execution = (int) GetTickCount(); wasordermodified = OrderModify ( OrderTicket(), orderprice, orderstoploss, ordertakeprofit, 0, Orange ); } // Order was modified if ( wasordermodified == TRUE ) { // Calculate Execution speed Execution = (int) GetTickCount() - Execution; // Print if debug or verbose if ( Debug || Verbose ) Print ( "Order executed in " + (string) Execution + " ms" ); } // Order was not modified else { // Reset Execution counter Execution = -1; // Add to errors sub_errormessages(); } } // Break out from endless loop break; } // count 1 more up counter1 ++; } // Price was NOT larger than the indicator, so delete the order // else // select = OrderDelete ( OrderTicket() ); } // end of switch } // end if OrderMagicNumber } // end for loopcount2 - end of loop through open orders // Calculate and keep track on global error number if ( GlobalError >= 0 || GlobalError == -2 ) { bidpart = (int) NormalizeDouble ( bid / Point, 0 ); askpart = (int) NormalizeDouble ( ask / Point, 0 ); if ( bidpart % 10 != 0 || askpart % 10 != 0 ) GlobalError = -1; else { if ( GlobalError >= 0 && GlobalError < 10 ) GlobalError ++; else GlobalError = -2; } } // Reset error-variable ordersenderror = FALSE; // Before executing new orders, lets check the average Execution time. if ( pricedirection != 0 && MaxExecution > 0 && Avg_execution > MaxExecution ) { pricedirection = 0; // Ignore the order opening triger if ( Debug || Verbose ) Print ( "Server is too Slow. Average Execution: " + (string) Avg_execution ); } // Set default price adjustment askplusdistance = ask + StopLevel+(DistanceInPips*Point); bidminusdistance = bid - StopLevel-(DistanceInPips*Point); // If we have no open orders AND a price breakout AND average spread is less or equal to max allowed spread AND we have no errors THEN proceed if ( counter1 == 0 && pricedirection != 0 && sub_normalizebrokerdigits ( realavgspread) <= sub_normalizebrokerdigits ( MaxSpread * Point ) && GlobalError == -1 && OrdersTotal()<1 ) { // If we have a price breakout downwards (Bearish) then send a BUYSTOP order if (pricedirection == 1 || /*pricedirection == -1 ||*/ pricedirection == 2 ) // Send a BUYSTOP { // Calculate a new price to use orderprice = ask + StopLevel; // SL and TP is not sent with order, but added afterwords in a OrderModify command if ( ECN_Mode == TRUE ) { // Set prices for OrderModify of BUYSTOP order orderprice = askplusdistance; orderstoploss = 0; ordertakeprofit = 0; // Start Execution counter Execution = (int) GetTickCount(); // Send a BUYSTOP order without SL and TP orderticket = OrderSend ( Symbol(), OP_BUYSTOP, LotSize, orderprice, Slippage, orderstoploss, ordertakeprofit, OrderCmt, Magic, 0, Lime ); // OrderSend was executed successfully if ( orderticket > 0 ) { // Calculate Execution speed Execution = (int) GetTickCount() - Execution; if ( Debug || Verbose ) Print ( "Order executed in " + (string) Execution + " ms" ); // If we have choosen to take snapshots and we're not backtesting, then do so } // end if ordersend // OrderSend was NOT executed else { ordersenderror = TRUE; Execution = -1; // Add to errors sub_errormessages(); } // OrderSend was executed successfully, so now modify it with SL and TP if ( OrderSelect ( orderticket, SELECT_BY_TICKET ) ) { RefreshRates(); // Set prices for OrderModify of BUYSTOP order orderprice = OrderOpenPrice(); orderstoploss = sub_normalizebrokerdigits ( orderprice - spread - StopLoss * Point - AddPriceGap ); ordertakeprofit = sub_normalizebrokerdigits ( orderprice + TakeProfit * Point + AddPriceGap ); // Start Execution timer Execution = (int) GetTickCount(); // Send a modify order for BUYSTOP order with new SL and TP wasordermodified = OrderModify ( OrderTicket(), orderprice, orderstoploss, ordertakeprofit, orderexpiretime, Blue ); // OrderModify was executed successfully if ( wasordermodified == TRUE ) { // Calculate Execution speed Execution = (int) GetTickCount() - Execution; if ( Debug || Verbose ) Print ( "Order executed in " + (string) Execution + " ms" ); } // end successful ordermodiify // Order was NOT modified else { ordersenderror = TRUE; Execution = -1; // Add to errors sub_errormessages(); } // end if-else } // end if ordermodify } // end if ECN_Mode // No ECN-mode, SL and TP can be sent directly else { RefreshRates(); // Set prices for BUYSTOP order orderprice = askplusdistance;//ask+StopLevel orderstoploss = sub_normalizebrokerdigits ( orderprice - spread - StopLoss * Point - AddPriceGap ); ordertakeprofit = sub_normalizebrokerdigits ( orderprice + TakeProfit * Point + AddPriceGap ); // Start Execution counter Execution = (int) GetTickCount(); // Send a BUYSTOP order with SL and TP orderticket = OrderSend ( Symbol(), OP_BUYSTOP, LotSize, orderprice, Slippage, orderstoploss, ordertakeprofit, OrderCmt, Magic, orderexpiretime, Blue ); if ( orderticket > 0 ) // OrderSend was executed suxxessfully { lastbuyprice=orderprice; lastorderbar=Bars; // Calculate Execution speed Execution = (int) GetTickCount() - Execution; if ( Debug || Verbose ) Print ( "Order executed in " + (string) Execution + " ms" ); } // end successful ordersend // Order was NOT sent else { ordersenderror = TRUE; // Reset Execution timer Execution = -1; // Add to errors sub_errormessages(); } // end if-else } // end no ECN-mode } // end if pricedirection == -1 or 2 // If we have a price breakout upwards (Bullish) then send a SELLSTOP order if (pricedirection == -1 || /*pricedirection == 1 ||*/ pricedirection == 2 ) { // Set prices for SELLSTOP order with zero SL and TP orderprice = bidminusdistance; orderstoploss = 0; ordertakeprofit = 0; // SL and TP cannot be sent with order, but must be sent afterwords in a modify command if (ECN_Mode==true) { // Start Execution timer Execution = (int) GetTickCount(); // Send a SELLSTOP order without SL and TP orderticket = OrderSend ( Symbol(), OP_SELLSTOP, LotSize, orderprice, Slippage, orderstoploss, ordertakeprofit, OrderCmt, Magic, 0, Red ); // OrderSend was executed successfully if ( orderticket > 0 ) { // Calculate Execution speed Execution = (int) GetTickCount() - Execution; if ( Debug || Verbose ) Print ( "Order executed in " + (string) Execution + " ms" ); } // end if ordersend // OrderSend was NOT executed else { ordersenderror = TRUE; Execution = -1; // Add to errors sub_errormessages(); } // If the SELLSTOP order was executed successfully, then select that order if ( OrderSelect(orderticket, SELECT_BY_TICKET ) ) { RefreshRates(); // Set prices for SELLSTOP order with modified SL and TP orderprice = OrderOpenPrice(); orderstoploss = sub_normalizebrokerdigits ( orderprice + spread + StopLoss * Point + AddPriceGap ); ordertakeprofit = sub_normalizebrokerdigits ( orderprice - TakeProfit * Point - AddPriceGap ); // Start Execution timer Execution = (int) GetTickCount(); // Send a modify order with adjusted SL and TP wasordermodified = OrderModify ( OrderTicket(), OrderOpenPrice(), orderstoploss, ordertakeprofit, orderexpiretime, Orange ); } // OrderModify was executed successfully if ( wasordermodified == TRUE ) { // Calculate Execution speed Execution = (int) GetTickCount() - Execution; // Print debug info if ( Debug || Verbose ) Print ( "Order executed in " + (string) Execution + " ms" ); } // end if ordermodify was executed successfully // Order was NOT executed else { ordersenderror = TRUE; // Reset Execution timer Execution = -1; // Add to errors sub_errormessages(); } } else // No ECN-mode, SL and TP can be sent directly { RefreshRates(); // Set prices for SELLSTOP order with SL and TP orderprice = bidminusdistance; orderstoploss = sub_normalizebrokerdigits ( orderprice + spread + StopLoss * Point + AddPriceGap ); ordertakeprofit = sub_normalizebrokerdigits ( orderprice - TakeProfit * Point - AddPriceGap ); // Start Execution timer Execution = (int) GetTickCount(); // Send a SELLSTOP order with SL and TP orderticket = OrderSend ( Symbol(), OP_SELLSTOP, LotSize, orderprice, Slippage, orderstoploss, ordertakeprofit, OrderCmt, Magic, orderexpiretime, Red ); // If OrderSend was executed successfully if ( orderticket > 0 ) { lastsellprice=orderprice; lastorderbar=Bars; // Calculate exection speed for that order Execution = (int) GetTickCount() - Execution; // Print debug info if ( Debug || Verbose ) Print ( "Order executed in " + (string) Execution + " ms" ); } // end successful ordersend // OrderSend was NOT executed successfully else { ordersenderror = TRUE; // Nullify Execution timer Execution = 0; // Add to errors sub_errormessages(); } // end if-else } // end no ECN-mode } // end pricedirection == 0 or 2 } // end if execute new orders // If we have no samples, every MaxExecutionMinutes a new OrderModify Execution test is done if ( MaxExecution && Execution == -1 && ( TimeLocal() - StartTime ) % MaxExecutionMinutes == 0 ) { // When backtesting, simulate random Execution time based on the setting if ( IsTesting() && MaxExecution ) { MathSrand ( (int) TimeLocal( )); Execution = MathRand() / ( 32767 / MaxExecution ); } else { // Unless backtesting, lets send a fake order to check the OrderModify Execution time, if ( IsTesting() == FALSE ) { // To be sure that the fake order never is executed, st the price to twice the current price fakeprice = ask * 2.0; // Send a BUYSTOP order orderticket = OrderSend ( Symbol(), OP_BUYSTOP, LotSize, fakeprice, Slippage, 0, 0, OrderCmt, Magic, 0, Blue ); Execution = (int) GetTickCount(); // Send a modify command where we adjust the price with +1 pip wasordermodified = OrderModify ( orderticket, fakeprice + 10 * Point, 0, 0, 0, Lime ); // Calculate Execution speed Execution = (int) GetTickCount() - Execution; // Delete the order select = OrderDelete(orderticket); } } } // Do we have a valid Execution sample? Update the average Execution time. if ( Execution >= 0 ) { // Consider only 10 samples at most. if ( Execution_samples < 10 ) Execution_samples ++; // Calculate average Execution speed Avg_execution = Avg_execution + ( Execution - Avg_execution ) / Execution_samples; } // Check initialization if ( GlobalError >= 0 ) Print ( "Robot is initializing..." ); else { // Error if ( GlobalError == -2 ) Print ( "ERROR -- Instrument " + Symbol() + " prices should have " + (string) BrokerDigits + " fraction digits on broker account" ); // No errors, ready to print else { textstring = TimeToStr ( TimeCurrent() ) + " Tick: " + sub_adjust00instring ( TickCounter ); // Only show / print this if Debug OR Verbose are set to TRUE if ( Debug || Verbose ) { // In case Execution is -1 (not yet calculate dvalue, set it to 0 for printing tmpexecution = Execution; if ( Execution == -1 ) tmpexecution = 0; // Prepare text string for printing textstring = textstring + "\n*** DEBUG MODE *** \nCurrency pair: " + Symbol() + ", Volatility: " + sub_dbl2strbrokerdigits ( volatility ) + ", VolatilityLimit: " + sub_dbl2strbrokerdigits ( VolatilityLimit ) + ", VolatilityPercentage: " + sub_dbl2strbrokerdigits ( volatilitypercentage ); textstring = textstring + "\nPriceDirection: " + StringSubstr ( "BUY NULLSELLBOTH", 4 * pricedirection + 4, 4 ) + ", Expire: " + TimeToStr ( orderexpiretime, TIME_MINUTES ) + ", Open orders: " + (string) counter1; textstring = textstring + "\nBid: " + sub_dbl2strbrokerdigits ( bid ) + ", Ask: " + sub_dbl2strbrokerdigits ( ask ) + ", " + indy; textstring = textstring + "\nAvgSpread: " + sub_dbl2strbrokerdigits ( avgspread ) + ", RealAvgSpread: " + sub_dbl2strbrokerdigits ( realavgspread ) + ", Commission: " + sub_dbl2strbrokerdigits ( Commission ) + ", Lots: " + DoubleToStr ( LotSize, 2 ) + ", Execution: " + (string) tmpexecution + " ms"; if ( sub_normalizebrokerdigits ( realavgspread ) > sub_normalizebrokerdigits ( MaxSpread * Point ) ) { textstring = textstring + "\n" + "The current spread (" + sub_dbl2strbrokerdigits ( realavgspread ) +") is higher than what has been set as MaxSpread (" + sub_dbl2strbrokerdigits ( MaxSpread * Point ) + ") so no trading is allowed right now on this currency pair!"; } if ( MaxExecution > 0 && Avg_execution > MaxExecution ) { textstring = textstring + "\n" + "The current Avg Execution (" + (string) Avg_execution +") is higher than what has been set as MaxExecution (" + (string) MaxExecution+ " ms), so no trading is allowed right now on this currency pair!"; } Print ( textstring ); // Only print this if we have a any orders OR have a price breakout OR Verbode mode is set to TRUE if ( counter1 != 0 || pricedirection != 0 ) sub_printformattedstring ( textstring ); } } // end if-else } // end check initialization // Check for stray market orders without SL sub_Check4StrayTrades(); } // end sub // Check for stray trades void sub_Check4StrayTrades() { // Initiate some local variables int loop; int totals; bool modified = TRUE; bool selected; double ordersl; double newsl; // New SL to use for modifying stray market orders is max of either current SL or 10 points newsl = MathMax ( StopLoss, 10 ); // Get number of open orders totals = OrdersTotal(); // Loop through all open orders from first to last for ( loop = 0; loop < totals; loop ++ ) { // Select on order if ( OrderSelect ( loop, SELECT_BY_POS, MODE_TRADES ) ) { // Check if it matches the MagicNumber and chart symbol if ( OrderMagicNumber() == Magic && OrderSymbol() == Symbol() ) // If the orders are for this EA { ordersl = OrderStopLoss(); // Continue as long as the SL for the order is 0.0 while ( ordersl == 0.0 ) { // We have found a Buy-order if ( OrderType() == OP_BUY ) { // Set new SL 10 points away from current price newsl = Bid - newsl * Point; modified = OrderModify ( OrderTicket(), OrderOpenPrice(), NormalizeDouble ( newsl, Digits ), OrderTakeProfit(), 0, Blue ); } // We have found a Sell-order else if ( OrderType() == OP_SELL ) { // Set new SL 10 points away from current price newsl = Ask + newsl * Point; modified = OrderModify ( OrderTicket(), OrderOpenPrice(), NormalizeDouble ( newsl, Digits ), OrderTakeProfit(), 0, Blue ); } // If the order without previous SL was modified wit a new SL if ( modified == TRUE ) { // Select that modified order, set while condition variable to that true value and exit while-loop selected = OrderSelect ( modified, SELECT_BY_TICKET, MODE_TRADES ); ordersl = OrderStopLoss(); break; } // If the order could not be modified else // if ( modified == FALSE ) { // Wait 1/10 second and then fetch new prices Sleep ( 100 ); RefreshRates(); // Print debug info if ( Debug || Verbose ) Print ( "Error trying to modify stray order with a SL!" ); // Add to errors sub_errormessages(); } } } } } } // Convert a decimal number to a text string string sub_dbl2strbrokerdigits ( double par_a ) { return ( DoubleToStr ( par_a, BrokerDigits ) ); } // Adjust numbers with as many decimals as the broker uses double sub_normalizebrokerdigits ( double par_a ) { return ( NormalizeDouble ( par_a, BrokerDigits ) ); } // Adjust textstring with zeros at the end string sub_adjust00instring ( int par_a ) { if ( par_a < 10 ) return ( "00" + (string) par_a ); if ( par_a < 100 ) return ( "0" + (string) par_a ); return ( "" + (string) par_a ); } // Print out formatted textstring void sub_printformattedstring ( string par_a ) { // Initiate some local variables int difference; int a = -1; // Loop through the text string from left to right to find a newline while ( a < StringLen ( par_a ) ) { difference = a + 1; a = StringFind ( par_a, "\n", difference ); if ( a == -1 ) { Print ( StringSubstr ( par_a, difference ) ); return; } // Print out the formatted text string, line for line Print ( StringSubstr ( par_a, difference, a - difference ) ); } } // Calculate lot multiplicator for Account Currency. Assumes that account currency is any of the 8 majors. // If the account currency is of any other currency, then calculate the multiplicator as follows: // If base-currency is USD then use the BID-price for the currency pair USDXXX; or if the // counter currency is USD the use 1 / BID-price for the currency pair XXXUSD, // where XXX is the abbreviation for the account currency. The calculated lot-size should // then be multiplied with this multiplicator. double sub_multiplicator() { // Initiate some local variables double marketbid = 0; double multiplicator = 1.0; int length; string appendix = ""; // If the account currency is USD if ( AccountCurrency() == "USD" ) return ( multiplicator ); length = StringLen ( Symbol() ); if ( length != 6 ) appendix = StringSubstr ( Symbol(), 6, length - 6 ); // If the account currency is EUR if ( AccountCurrency() == "EUR" ) { marketbid = MarketInfo ( "EURUSD" + appendix, MODE_BID ); if ( marketbid != 0 ) multiplicator = 1.0 / marketbid; else { Print ( "WARNING! Unable to fetch the market Bid price for " + AccountCurrency() + ", will use the static value 1.0 instead!" ); multiplicator = 1.0; } } // If the account currency is GBP if ( AccountCurrency() == "GBP" ) { marketbid = MarketInfo ( "GBPUSD" + appendix, MODE_BID ); if ( marketbid != 0 ) multiplicator = 1.0 / marketbid; else { Print ( "WARNING! Unable to fetch the market Bid price for " + AccountCurrency() + ", will use the static value 1.5 instead!" ); multiplicator = 1.5; } } // If the account currenmmcy is AUD if ( AccountCurrency() == "AUD" ) { marketbid = MarketInfo ( "AUDUSD" + appendix, MODE_BID ); if ( marketbid != 0 ) multiplicator = 1.0 / marketbid; else { Print ( "WARNING! Unable to fetch the market Bid price for " + AccountCurrency() + ", will use the static value 0.7 instead!" ); multiplicator = 0.7; } } // If the account currency is NZD if ( AccountCurrency() == "NZD" ) { marketbid = MarketInfo ( "NZDUSD" + appendix, MODE_BID ); if ( marketbid != 0 ) multiplicator = 1.0 / marketbid; else { Print ( "WARNING! Unable to fetch the market Bid price for " + AccountCurrency() + ", will use the static value 0.65 instead!" ); multiplicator = 0.65; } } // If the account currency is CHF if ( AccountCurrency() == "CHF" ) { marketbid = MarketInfo ( "USDCHF" + appendix, MODE_BID ); if ( marketbid != 0 ) multiplicator = 1.0 / marketbid; else { Print ( "WARNING! Unable to fetch the market Bid price for " + AccountCurrency() + ", will use the static value 1.0 instead!" ); multiplicator = 1.0; } } // If the account currenmmcy is JPY if ( AccountCurrency() == "JPY" ) { marketbid = MarketInfo ( "USDJPY" + appendix, MODE_BID ); if ( marketbid != 0 ) multiplicator = 1.0 / marketbid; else { Print ( "WARNING! Unable to fetch the market Bid price for " + AccountCurrency() + ", will use the static value 120 instead!" ); multiplicator = 120; } } // If the account currenmcy is CAD if ( AccountCurrency() == "CAD" ) { marketbid = MarketInfo ( "USDCAD" + appendix, MODE_BID ); if ( marketbid != 0 ) multiplicator = 1.0 / marketbid; else { Print ( "WARNING! Unable to fetch the market Bid price for " + AccountCurrency() + ", will use the static value 1.3 instead!" ); multiplicator = 1.3; } } // If account currency is neither of EUR, GBP, AUD, NZD, CHF, JPY or CAD we assumes that it is USD if ( multiplicator == 0 ) multiplicator = 1.0; // Return the calculated multiplicator value for the account currency return ( multiplicator ); } // Magic Number - calculated from a sum of account number + ASCII-codes from currency pair int sub_magicnumber () { // Initiate some local variables string a; string b; int c; int d; int i; string par = "EURUSDJPYCHFCADAUDNZDGBP"; string sym = Symbol(); a = StringSubstr ( sym, 0, 3 ); b = StringSubstr ( sym, 3, 3 ); c = StringFind ( par, a, 0 ); d = StringFind ( par, b, 0 ); i = 999999999 - AccountNumber() - c - d; if ( Debug == TRUE ) Print ( "MagicNumber: ", i ); return ( i ); } // Main routine for making a screenshoot / printscreen void sub_takesnapshot() { // Initiate some local variables static datetime lastbar; static int doshot = -1; static int oldphase = 3000000; int phase=0; // Check to see that one bar has passed by if ( Time[0] != lastbar ) { lastbar = Time[0]; //doshot = DelayTicks; } // Reset varioable oldphase = phase; // If no screen shot has been taken then do it now if ( doshot == 0 ) sub_makescreenshot ( "" ); // A screen shot has already been taken, so decrease counter if ( doshot >= 0 ) doshot -= 1; } // Make a screenshoot / printscreen void sub_makescreenshot ( string par_sx = "" ) { // Initate a local variables static int no = 0; string fn; // Increase counter no ++; // Prepare textstring as filename to be saved fn = "SnapShot" + Symbol() + (string) Period() + "\\" + (string) Year() + "-" + sub_maketimestring ( Month(), 2 ) + "-" + sub_maketimestring ( Day(), 2 ) + " " + sub_maketimestring ( Hour(), 2 ) + "_" + sub_maketimestring ( Minute(), 2 ) + "_" + sub_maketimestring ( Seconds( ), 2 ) + " " + (string) no + (string) par_sx + ".gif"; // Make a scrren shot, and i there is an error when a screen shot should have been taken then print out error message if ( !ScreenShot ( fn, 640, 480 ) ) Print ( "ScreenShot error: ", ErrorDescription ( GetLastError() ) ); } // Add leading zeros that the resulting string has 'digits' length. string sub_maketimestring ( int par_number, int par_digits ) { // Initiate a local variable string result; result = DoubleToStr ( par_number, 0 ); while ( StringLen ( result ) < par_digits ) result = "0" + result; return ( result ); } // Calculate LotSize based on Equity, Risk (in %) and StopLoss in points double sub_calculatelotsize() { // initiate some localö variables string textstring; double lotsize=ManualLotsize; double maxlot=0; double minlot=0; int lotdigit = 0; // Adjust lot decimals to broker lotstep if ( LotStep == 1) lotdigit = 0; if ( LotStep == 0.1 ) lotdigit = 1; if ( LotStep == 0.01 ) lotdigit = 2; if ( MoneyManagement == True ) lotsize=Risk1(); // Use manual fix LotSize, but if necessary adjust to within limits else if ( MoneyManagement == FALSE ) { // Set LotSize to manual LotSize lotsize = ManualLotsize; // Check if ManualLotsize is greater than allowed LotSize if ( ManualLotsize > maxlot ) { lotsize = maxlot; textstring = "Note: Manual LotSize is too high. It has been recalculated to maximum allowed " + DoubleToStr ( maxlot, 2 ); Print ( textstring ); ManualLotsize = maxlot; } // ManualLotSize is NOT greater than allowed LotSize else if ( ManualLotsize < minlot ) lotsize = minlot; } return ( lotsize ); } // Re-calculate a new Risk if the current one is too low or too high void sub_recalculatewrongrisk() { // Initiate some local variables string textstring; double availablemoney; double maxlot; double minlot; double maxrisk; double minrisk; // Get available amount of money as Equity availablemoney = AccountEquity(); // Maximum allowed Lot by the broker according to Equity maxlot = MathFloor ( availablemoney / MarginForOneLot / LotStep ) * LotStep; // Maximum allowed Risk by the broker according to maximul allowed Lot and Equity maxrisk = MathFloor ( maxlot * ( StopLevel + StopLoss ) / availablemoney * 100 / 0.1 ) * 0.1; // Minimum allowed Lot by the broker minlot = MinLots; // Minimum allowed Risk by the broker according to minlots_broker minrisk = MathRound ( minlot * StopLoss / availablemoney * 100 / 0.1 ) * 0.1; // Empty textstring textstring = ""; // If we use money management if ( MoneyManagement == TRUE ) { // If Risk% is greater than the maximum risklevel the broker accept, then adjust Risk accordingly and print out changes if ( Risk > maxrisk ) { textstring = textstring + "Note: Risk has manually been set to " + DoubleToStr ( Risk, 1 ) + " but cannot be higher than " + DoubleToStr ( maxrisk, 1 ) + " according to "; textstring = textstring + "the broker, StopLoss and Equity. It has now been adjusted accordingly to " + DoubleToStr ( maxrisk, 1 ) + "%"; Risk = maxrisk; sub_printandcomment ( textstring ); } // If Risk% is less than the minimum risklevel the broker accept, then adjust Risk accordingly and print out changes if (Risk < minrisk) { textstring = textstring + "Note: Risk has manually been set to " + DoubleToStr ( Risk, 1 ) + " but cannot be lower than " + DoubleToStr ( minrisk, 1 ) + " according to "; textstring = textstring + "the broker, StopLoss, AddPriceGap and Equity. It has now been adjusted accordingly to " + DoubleToStr ( minrisk, 1 ) + "%"; Risk = minrisk; sub_printandcomment ( textstring ); } } // If we don't use MoneyManagement, then use fixed manual LotSize else // MoneyManagement == FALSE { // Check and if necessary adjust manual LotSize to external limits if ( ManualLotsize < MinLots ) { textstring = "Manual LotSize " + DoubleToStr ( ManualLotsize, 2 ) + " cannot be less than " + DoubleToStr ( MinLots, 2 ) + ". It has now been adjusted to " + DoubleToStr ( MinLots, 2); ManualLotsize = MinLots; sub_printandcomment ( textstring ); } if ( ManualLotsize > MaxLots ) { textstring = "Manual LotSize " + DoubleToStr ( ManualLotsize, 2 ) + " cannot be greater than " + DoubleToStr ( MaxLots, 2 ) + ". It has now been adjusted to " + DoubleToStr ( MinLots, 2 ); ManualLotsize = MaxLots; sub_printandcomment ( textstring ); } // Check to see that manual LotSize does not exceeds maximum allowed LotSize if ( ManualLotsize > maxlot ) { textstring = "Manual LotSize " + DoubleToStr ( ManualLotsize, 2 ) + " cannot be greater than maximum allowed LotSize. It has now been adjusted to " + DoubleToStr ( maxlot, 2 ); ManualLotsize = maxlot; sub_printandcomment ( textstring ); } } } // Print out broker details and other info void sub_printdetails() { // Initiate some local variables string margintext; string stopouttext; string fixedlots; int type; int freemarginmode; int stopoutmode; double newsl; // Prepare some text strings newsl = MathMax ( StopLoss, 10 ); type = IsDemo() + IsTesting(); freemarginmode = AccountFreeMarginMode(); stopoutmode = AccountStopoutMode(); if ( freemarginmode == 0 ) margintext = "that floating profit/loss is not used for calculation."; else if ( freemarginmode == 1 ) margintext = "both floating profit and loss on open positions."; else if ( freemarginmode == 2 ) margintext = "only profitable values, where current loss on open positions are not included."; else if ( freemarginmode == 3 ) margintext = "only loss values are used for calculation, where current profitable open positions are not included."; if ( stopoutmode == 0 ) stopouttext = "percentage ratio between margin and equity."; else if ( stopoutmode == 1 ) stopouttext = "comparison of the free margin level to the absolute value."; if ( MoneyManagement == TRUE ) fixedlots = " (automatically calculated lots)."; if ( MoneyManagement == FALSE ) fixedlots = " (fixed manual lots)."; /*Print ( "Broker name: ", AccountCompany() ); Print ( "Broker server: ", AccountServer() ); Print ( "Account type: ", StringSubstr ( "RealDemoTest", 4 * type, 4) ); Print ( "Initial account equity: ", AccountEquity()," ", AccountCurrency() ); Print ( "Broker digits: ", BrokerDigits); Print ( "Broker StopLevel / freezelevel (max): ", StopLevel ); Print ( "Broker StopOut level: ", StopOut, "%" ); Print ( "Broker Point: ", DoubleToStr ( Point, BrokerDigits )," on ", AccountCurrency() ); Print ( "Broker account Leverage in percentage: ", Leverage ); Print ( "Broker credit value on the account: ", AccountCredit() ); Print ( "Broker account margin: ", AccountMargin() ); Print ( "Broker calculation of free margin allowed to open positions considers " + margintext ); Print ( "Broker calculates StopOut level as " + stopouttext ); Print ( "Broker requires at least ", MarginForOneLot," ", AccountCurrency()," in margin for 1 lot." ); Print ( "Broker set 1 lot to trade ", LotBase," ", AccountCurrency() ); Print ( "Broker minimum allowed LotSize: ", MinLots ); Print ( "Broker maximum allowed LotSize: ", MaxLots ); Print ( "Broker allow lots to be resized in ", LotStep, " steps." ); Print ( "Risk: ", Risk, "%" ); Print ( "Risk adjusted LotSize: ", DoubleToStr ( LotSize, 2 ) + fixedlots );*/ } // Print and show comment of text void sub_printandcomment ( string par_text ) { Print ( par_text ); } // Summarize error messages that comes from the broker server void sub_errormessages() { // Initiate a local variable int error = GetLastError(); // Depending on the value if the variable error, one case should match and the counter for that errtor should be increased with 1 switch ( error ) { // Unchanged values case 1: // ERR_SERVER_BUSY: { Err_unchangedvalues ++; break; } // Trade server is busy case 4: // ERR_SERVER_BUSY: { Err_busyserver ++; break; } case 6: // ERR_NO_CONNECTION: { Err_lostconnection ++; break; } case 8: // ERR_TOO_FREQUENT_REQUESTS: { Err_toomanyrequest ++; break; } case 129: // ERR_INVALID_PRICE: { Err_invalidprice ++; break; } case 130: // ERR_INVALID_STOPS: { Err_invalidstops ++; break; } case 131: // ERR_INVALID_TRADE_VOLUME: { Err_invalidtradevolume ++; break; } case 135: // ERR_PRICE_CHANGED: { Err_pricechange ++; break; } case 137: // ERR_BROKER_BUSY: { Err_brokerbuzy ++; break; } case 138: // ERR_REQUOTE: { Err_requotes ++; break; } case 141: // ERR_TOO_MANY_REQUESTS: { Err_toomanyrequests ++; break; } case 145: // ERR_TRADE_MODIFY_DENIED: { Err_trademodifydenied ++; break; } case 146: // ERR_TRADE_CONTEXT_BUSY: { Err_tradecontextbuzy ++; break; } } } // Print out and comment summarized messages from the broker void sub_printsumofbrokererrors() { // Prepare some lopcal variables string txt; int totalerrors; // Prepare a text strring txt = "Number of times the brokers server reported that "; // Sum up total errors totalerrors = Err_unchangedvalues + Err_busyserver + Err_lostconnection + Err_toomanyrequest + Err_invalidprice + Err_invalidstops + Err_invalidtradevolume + Err_pricechange + Err_brokerbuzy + Err_requotes + Err_toomanyrequests + Err_trademodifydenied + Err_tradecontextbuzy; // Call print subroutine with text depending on found errors if ( Err_unchangedvalues > 0 ) sub_printandcomment ( txt + "SL and TP was modified to existing values: " + DoubleToStr ( Err_unchangedvalues, 0 ) ); if ( Err_busyserver > 0 ) sub_printandcomment ( txt + "it is buzy: " + DoubleToStr ( Err_busyserver, 0 ) ); if ( Err_lostconnection > 0 ) sub_printandcomment ( txt + "the connection is lost: " + DoubleToStr ( Err_lostconnection, 0 ) ); if ( Err_toomanyrequest > 0 ) sub_printandcomment ( txt + "there was too many requests: " + DoubleToStr ( Err_toomanyrequest, 0 ) ); if ( Err_invalidprice > 0 ) sub_printandcomment ( txt + "the price was invalid: " + DoubleToStr ( Err_invalidprice, 0 ) ); if ( Err_invalidstops > 0 ) sub_printandcomment ( txt + "invalid SL and/or TP: " + DoubleToStr ( Err_invalidstops, 0 ) ); if ( Err_invalidtradevolume > 0 ) sub_printandcomment ( txt + "invalid lot size: " + DoubleToStr ( Err_invalidtradevolume, 0 ) ); if ( Err_pricechange > 0 ) sub_printandcomment(txt + "the price has changed: " + DoubleToStr ( Err_pricechange, 0 ) ); if ( Err_brokerbuzy > 0 ) sub_printandcomment(txt + "the broker is buzy: " + DoubleToStr ( Err_brokerbuzy, 0 ) ) ; if ( Err_requotes > 0 ) sub_printandcomment ( txt + "requotes " + DoubleToStr ( Err_requotes, 0 ) ); if ( Err_toomanyrequests > 0 ) sub_printandcomment ( txt + "too many requests " + DoubleToStr ( Err_toomanyrequests, 0 ) ); if ( Err_trademodifydenied > 0 ) sub_printandcomment ( txt + "modifying orders is denied " + DoubleToStr ( Err_trademodifydenied, 0 ) ); if ( Err_tradecontextbuzy > 0) sub_printandcomment ( txt + "trade context is buzy: " + DoubleToStr ( Err_tradecontextbuzy, 0 ) ); if ( totalerrors == 0 ) sub_printandcomment ( "There was no error reported from the broker server!" ); } // Check through all open orders void sub_CheckThroughAllOpenOrders() { // Initiate some local variables int pos; double tmp_order_lots; double tmp_order_price; // Get total number of open orders Tot_Orders = OrdersTotal(); // Reset counters Tot_open_pos = 0; Tot_open_profit = 0; Tot_open_lots = 0; Tot_open_swap = 0; Tot_open_commission = 0; G_equity = 0; Changedmargin = 0; // Loop through all open orders from first to last for ( pos = 0; pos < Tot_Orders; pos ++ ) { // Select on order if ( OrderSelect ( pos, SELECT_BY_POS, MODE_TRADES ) ) { // Check if it matches the MagicNumber if ( OrderMagicNumber() == Magic && OrderSymbol() == Symbol() ) // If the orders are for this EA { // Calculate sum of open orders, open profit, swap and commission Tot_open_pos ++; tmp_order_lots = OrderLots(); Tot_open_lots += tmp_order_lots; tmp_order_price = OrderOpenPrice(); Tot_open_profit += OrderProfit(); Tot_open_swap += OrderSwap(); Tot_open_commission += OrderCommission(); Changedmargin += tmp_order_lots * tmp_order_price; } } } // Calculate Balance and Equity for this EA and not for the entire account G_equity = G_balance + Tot_open_profit + Tot_open_swap + Tot_open_commission; } // Check through all closed orders void sub_CheckThroughAllClosedOrders() { // Initiate some local variables int pos; int openTotal = OrdersHistoryTotal(); // Reset counters Tot_closed_pos = 0; Tot_closed_lots = 0; Tot_closed_profit = 0; Tot_closed_swap = 0; Tot_closed_comm = 0; G_balance = 0; // Loop through all closed orders for ( pos = 0; pos < openTotal; pos ++ ) { // Select one order if ( OrderSelect ( pos, SELECT_BY_POS, MODE_HISTORY ) ) // Loop through the history pool of closed and deleted orders { // If the MagicNumber matches if ( OrderMagicNumber() == Magic && OrderSymbol() == Symbol() ) // If the orders are for this EA { // Fetch order info Tot_closed_lots += OrderLots(); Tot_closed_profit += OrderProfit(); Tot_closed_swap += OrderSwap(); Tot_closed_comm += OrderCommission(); // Count number of closed total orders for this EA Tot_closed_pos ++; } } } G_balance = Tot_closed_profit + Tot_closed_swap + Tot_closed_comm; } // Printout graphics on the chart void sub_ShowGraphInfo() { sub_Display ( "ACCOUNT_BKG", "ggggg", "Webdings" , 25, 5, 59, LightBlue, 0 ); sub_Display ( "ACCOUNT_BKG2", "ggggg", "Webdings" , 25, 5, 92, LightBlue, 0 ); sub_Display ( "ACCOUNT_BKG3", "ggggg", "Webdings" , 25, 5, 125, LightBlue, 0 ); sub_Display ( "ACCOUNT_BKG4", "ggggg", "Webdings" , 25, 5, 150, LightBlue, 0 ); sub_Display ( "BKG_HEAD1", "ggggg", "Webdings" , 25, 5, 15, SkyBlue, 0 ); sub_Display ( "BKG_HEAD2", "ggggg", "Webdings" , 25, 5, 31, SkyBlue, 0 ); sub_Display ( "OCTOPUS_TEXT", " MidasamaTrader EA_Full Unlimited", "Times New Roman" , 20, 5, 17, White, 0 ); sub_Display ( "ACCOUNT_TEXT", " Account: ", "Tahoma Bold" , 10, 5, 80, LightSeaGreen, 0 ); sub_Display ( "ACCOUNT_VALUE", string(AccountNumber()), "Tahoma Bold" , 9, 94, 80, Black, 0 ); sub_Display ( "BALANCE_TEXT", " Balance: ", "Tahoma Bold" , 10, 5, 100, LightSeaGreen, 0 ); sub_Display ( "BALANCE_VALUE", DoubleToStr ( AccountBalance(), 2 ), "Tahoma Bold" , 9, 94, 100, Black, 0 ); sub_Display ( "EQUITY_TEXT", " Equity: ", "Tahoma Bold" , 10, 5, 120, LightSeaGreen, 0 ); sub_Display ( "EQUITY_VALUE", DoubleToStr ( AccountEquity(), 2 ), "Tahoma Bold" , 9, 94, 120, Black, 0 ); sub_Display ( "FREE_MARGIN_TEXT", " Spread: ", "Tahoma Bold" , 10, 5, 140, LightSeaGreen, 0 ); sub_Display ( "FREE_MARGIN_VALUE",string(MarketInfo(Symbol(),MODE_SPREAD)) , "Tahoma Bold" , 9, 94, 140, Black, 0 ); } // Subroutine for displaying graphics on the chart void sub_Display ( string obj_name, string object_text, string object_text_font, int object_text_fontsize, int object_x_distance, int object_y_distance, color object_textcolor, int object_corner_value ) { ObjectCreate ( obj_name, OBJ_LABEL, 0, 0, 0, 0, 0 ); ObjectSet ( obj_name, OBJPROP_CORNER, object_corner_value ); ObjectSet ( obj_name, OBJPROP_XDISTANCE, object_x_distance ); ObjectSet ( obj_name, OBJPROP_YDISTANCE, object_y_distance ); ObjectSetText ( obj_name, object_text, object_text_fontsize, object_text_font, object_textcolor ); } // Delete all graphics on the chart void sub_DeleteDisplay() { ObjectsDeleteAll(); } // Get text for Uninit Reason string sub_UninitReasonText( int reasonCode ) { string text = ""; switch ( reasonCode ) { case REASON_ACCOUNT: text = "Account was changed"; break; case REASON_CHARTCHANGE: text = "Symbol or timeframe was changed"; break; case REASON_CHARTCLOSE: text = "Chart was closed"; break; case REASON_PARAMETERS: text = "Input-parameter was changed"; break; case REASON_RECOMPILE: text = "Program " + __FILE__ + " was recompiled"; break; case REASON_REMOVE: text = "Program " + __FILE__ + " was removed from chart"; break; case REASON_TEMPLATE: text = "New template was applied to chart"; break; default: text = "Another reason"; } return ( text ); } void breakEvenManager() { double pAsk = Ask; double pBid = Bid; int err=-1; for(int i=OrdersTotal()-1; i>=0; i--) { dummyResult = OrderSelect(i, SELECT_BY_POS, MODE_TRADES); if(OrderSymbol() != Symbol()) continue; if(OrderMagicNumber()!= Magic) continue; if (OrderType()==OP_BUY) { if (pBid-OrderOpenPrice()>pPoint*Breakeven) { double BuyStop = OrderOpenPrice()+LockInPips*pPoint; if (OrderStopLoss() < BuyStop) err = OrderModify(OrderTicket(),NormalizeDouble(OrderOpenPrice(),digit),NormalizeDouble(BuyStop,digit),NormalizeDouble(OrderTakeProfit(),digit),LightGreen); if (err==true) //Print("Error: "+(string)GetLastError()); //else Print("BreakingEven..."); return; } } if (OrderType()==OP_SELL) { if (OrderOpenPrice()-pAsk > pPoint*Breakeven) { double SellStop = OrderOpenPrice()-LockInPips*pPoint; if (OrderStopLoss() > SellStop) err = OrderModify(OrderTicket(),NormalizeDouble(OrderOpenPrice(),digit),NormalizeDouble(SellStop,digit),NormalizeDouble(OrderTakeProfit(),digit),DarkOrange); if (err==true) //Print("Error: "+(string)GetLastError()); //else Print("BreakingEven..."); return; } } } } //+--------------------------------------------------------------- void CloseThisSymbolAllPending() { for (int trade = OrdersTotal() - 1; trade >= 0; trade--) { if ( OrderSelect(trade, SELECT_BY_POS, MODE_TRADES) ) { if (OrderSymbol() == Symbol()) { if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic) { if (OrderType() == OP_BUYSTOP) { if (OrderDelete(OrderTicket(), Green)) Print("Order Deleted Succesfully"); else Print("OrderDelete returned the error of ",GetLastError()); } if (OrderType() == OP_SELLSTOP) { if (OrderDelete(OrderTicket(),Red)) Print("Order Deleted Succesfully"); else Print("OrderDelete returned the error of ",GetLastError()); } } Sleep(1000); } }else Print("OrderSelect returned the error of ",GetLastError()); } } //+------------------------------------------------------------------+ void TrailingAlls(double pType, double stop) { double stoptrade; double stopcal; int err=-1; if (stop != 0) { for (int trade = OrdersTotal() - 1; trade >= 0; trade--) { if (OrderSelect(trade, SELECT_BY_POS, MODE_TRADES)) { if (OrderSymbol() != Symbol() /*|| OrderMagicNumber() != MagicBuy || OrderMagicNumber() != MagicSell*/) continue; if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic) { if (OrderType() == OP_BUY) { //profit = NormalizeDouble(OrderProfit(),2); // if (profit < pType) continue; if (Bid-OrderOpenPrice() < pType*Point) continue; //Alert(Bid-OrderOpenPrice(),"====",pType); stoptrade = OrderStopLoss(); stopcal = Bid - stop * Point; if (stoptrade == 0.0 || (stoptrade != 0.0 && stopcal > stoptrade)) err=OrderModify(OrderTicket(), OrderOpenPrice(), stopcal, OrderTakeProfit(), 0, Aqua); if (err==true) //Print("Error: "+(string)GetLastError()); //else Print("Trailing..."); } if (OrderType() == OP_SELL) { //profit = NormalizeDouble(OrderProfit(),2); //if (OrderProfit() < pType) continue; if ( (OrderOpenPrice()-Ask)/Point < pType*Point) continue; // Alert(OrderOpenPrice()-Ask,"====",pType,"====",OrderProfit()); stoptrade = OrderStopLoss(); stopcal = Ask + stop * Point; if (stoptrade == 0.0 || (stoptrade != 0.0 && stopcal < stoptrade)) err=OrderModify(OrderTicket(), OrderOpenPrice(), stopcal, OrderTakeProfit(), 0, Aqua); if (err==true) //Print("Error: "+(string)GetLastError()); //else Print("Trailing..."); } } Sleep(100); } } } } //+------------------------------------------------------------------+ int CountTrades() { int count = 0; int ticket; for (int trade = OrdersTotal() - 1; trade >= 0; trade--) { if ( OrderSelect(trade, SELECT_BY_POS, MODE_TRADES) ) { if (OrderSymbol() != Symbol() || OrderMagicNumber() != Magic) continue; if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic) if (OrderType() == OP_SELL) {count+=10;ticket=OrderTicket();} if (OrderType() == OP_BUY) {count+=100;ticket=OrderTicket();} if ( OrderType() == OP_SELLSTOP) count++; if (OrderType() == OP_BUYSTOP) count+=4; }else Print("OrderSelect returned the error of ",GetLastError()); } return (count); } //+------------------------------------------------------------------+ // Use Percent Risk | //+------------------------------------------------------------------+ double Risk1() { double LTMTHOD=AccountBalance(); double percent=Risk; double lotsize_bn = NormalizeDouble((LTMTHOD*(percent/100)/1000.0),2); if (lotsize_bn