using System; using System.Linq; using cAlgo.API; using cAlgo.API.Indicators; using cAlgo.API.Internals; using cAlgo.Indicators; // Description:  // =========== //  Using cTrader and only trading using either a set time (GMT) or take the high and low of the previous configurable time-frame candle then calculate and enter a pending buy stop entry and a pending sell     stop entry.  // Customer: Louis Fernandes // LFStrategy B version 0.1 on 14.12.2016  // // Additional Versions - bug fixes and enhancements // =================== namespace cAlgo {     [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]     public class LFStrategyB : Robot     {         #region user defined parameters         [Parameter("Instance Name", DefaultValue = "001")]         public string InstanceName { get; set; }         [Parameter("Include Time Trading?", DefaultValue = true)]         public bool IncludeTradeStartTime { get; set; }         [Parameter("Trade Start Time (GMT)", DefaultValue = "05:45")]         public string TradeStartTime { get; set; }         [Parameter("Include Time-Frame Trading?", DefaultValue = true)]         public bool IncludeTradeOnTimeFrame { get; set; }         [Parameter("Risk %", DefaultValue = 5.0, MaxValue = 10.0)]         public double RiskPercent { get; set; }         [Parameter("Use Fixed Lot Size?", DefaultValue = true)]         public bool UseFixedLotSize { get; set; }         [Parameter("Lot Size", DefaultValue = 0.1)]         public double LotSize { get; set; }         [Parameter("Stop Loss (pips)", DefaultValue = 25)]         public double StopLoss { get; set; }         [Parameter("Take Profit (pips)", DefaultValue = 50)]         public double TakeProfit { get; set; }         [Parameter("Include Long Trades?", DefaultValue = true)]         public bool IncludeLong { get; set; }         [Parameter("Include Short Trades?", DefaultValue = true)]         public bool IncludeShort { get; set; }         [Parameter("Allow Multiple Orders", DefaultValue = false)]         public bool IncludeMultipleOrders { get; set; }         [Parameter("Pip Offset?", DefaultValue = 3)]         public int PipOffset { get; set; }         [Parameter("Include Trailing Stop", DefaultValue = false)]         public bool IncludeTrailingStop { get; set; }         [Parameter("Trailing Stop Trigger (pips)", DefaultValue = 40, MinValue = 1)]         public int TrailingStopTrigger { get; set; }         [Parameter("Trailing Stop Step (pips)", DefaultValue = 20, MinValue = 1)]         public int TrailingStopStep { get; set; }         #endregion         #region private fields         private string version = "v0.1";         private int tradeStartHour = 0;         private int tradeStartMin = 0;         private int tradeStopHour = 0;         private int tradeStopMin = 0;         #endregion         #region timezones         TimeZoneInfo timeZoneGMT = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");         #endregion         #region cAlgo events         ///          /// called once when robot starts         ///          protected override void OnStart()         {             // print version to log file             Print(version);             DateTime dtGMT = ExchangeTime(timeZoneGMT);             // get start time             string[] startTime = TradeStartTime.Split(':');             tradeStartHour = Convert.ToInt16(startTime[0]);             tradeStartMin = Convert.ToInt16(startTime[1]);             Print("Current GMT time: " + dtGMT.ToShortTimeString());             // event handler delegate to capture opened positions and close other order             Positions.Opened += OnPositionOpened;         }         ///          /// called every incoming tick of data         ///          protected override void OnTick()         {             DateTime dtGMT = ExchangeTime(timeZoneGMT);             // adjust trailing stop              if (IncludeTrailingStop)             {                 foreach (var p in this.Positions.Where(x => (x.Label == InstanceName)).Where(x => x.SymbolCode == Symbol.Code))                 {                     SetTrailingStopAdjustment(p, TrailingStopTrigger, TrailingStopStep);                 }             }             //  Open a buy and sell stop pending order daily at 05:45AM (GMT)             if (IncludeTradeStartTime)             {                 if (dtGMT.Hour == tradeStartHour && dtGMT.Minute == tradeStartMin)                 {                     SubmitPendingOrders();                 }             }         }         ///          /// called when candle closes and new one opens         ///          protected override void OnBar()         {             // if multiple orders are not allowed, do not cancel un-filled pending orders             if (!IncludeMultipleOrders)             {                 // All non-triggered orders should be canceled at the start of the next candle                 CancelPendingOrders();             }             // Open a buy and sell stop pending order at the start of a new candle             if (IncludeTradeOnTimeFrame)             {                 SubmitPendingOrders();             }         }         private void OnPositionOpened(PositionOpenedEventArgs args)         {             var position = args.Position;             if (position.Label == InstanceName && position.SymbolCode == this.Symbol.Code)             {                 Print("Pending order has triggered to open a " + args.Position.TradeType.ToString() + " position.");             }         }         #endregion         #region Trade logic         ///          /// submit pending orders only is target price has been reached.         ///          private void SubmitPendingOrders()         {             long volume = Symbol.QuantityToVolume(LotSize);             volume = Symbol.NormalizeVolume(volume);             // calculate long entry price last candle high             double targetPriceLong = GetLongEntryPrice();             double targetPriceShort = GetShortEntryPrice();             if (!UseFixedLotSize)             {                 // get risk based volume                 volume = GetVolumeFromPercent();             }             if (IncludeLong)             {                 // Buy Pending order should only be placed if current price is (default) 5 pips below the calculated entry price                  if (Symbol.Bid <= targetPriceLong)                 {                     PlaceStopOrder(TradeType.Buy, Symbol, volume, targetPriceLong, InstanceName, StopLoss, TakeProfit);                     Print("Buy Stop Order placed with entry price at " + targetPriceLong.ToString() + " with a volume of " + volume.ToString());                 }             }             if (IncludeShort)             {                 if (Symbol.Ask >= targetPriceShort)                 {                     // Sell Pending order should only be placed if current price is (default) 5 pips above the calculated entry price                     PlaceStopOrder(TradeType.Sell, Symbol, volume, targetPriceShort, InstanceName, StopLoss, TakeProfit);                     Print("Sell Stop Order placed with entry price at " + targetPriceShort.ToString() + " with a volume of " + volume.ToString());                 }             }         }         ///          /// cancels all open pending orders         ///          private void CancelPendingOrders()         {             foreach (var po in this.PendingOrders)             {                 if (po != null)                 {                     TradeResult result = CancelPendingOrder(po);                     if (result.IsSuccessful)                     {                         Print(result.PendingOrder.TradeType.ToString() + " Pending order canceled.");                     }                     else                     {                         Print("Error occurred canceling a pending order");                     }                 }             }         }         ///          /// adjusts all open positions with a trailing stop         ///          ///          ///          ///          ///          private bool SetTrailingStopAdjustment(Position p, double trigger, double trailing)         {             try             {                 bool TradeTypeBuy = true;                 if (p.TradeType == TradeType.Sell)                 {                     TradeTypeBuy = false;                 }                 double profit = TradeTypeBuy ? Symbol.Bid - p.EntryPrice : p.EntryPrice - Symbol.Ask;                 if (profit >= trigger * Symbol.PipSize)                 {                     double newStopLossPrice = TradeTypeBuy ? Math.Round(Symbol.Bid - trailing * Symbol.PipSize, Symbol.Digits) : Math.Round(Symbol.Ask + trailing * Symbol.PipSize, Symbol.Digits);                     bool modify = TradeTypeBuy ? newStopLossPrice > p.StopLoss : newStopLossPrice < p.StopLoss;                     if (modify)                     {                         ModifyPosition(p, newStopLossPrice, p.TakeProfit);                         Print("Trailing stop was modified.");                         return true;                     }                 }             } catch             {             }             return false;         }         #endregion         #region Risk percent per trade         ///          ///          ///          ///          ///          private int GetVolumeFromPercent()         {             double risk = RiskPercent / 100.0;             double volume;             volume = Account.Equity * risk / (StopLoss * Symbol.PipValue);             return (int)Symbol.NormalizeVolume(volume);         }         #endregion         #region calculations         // return the exact date and time for the exchange locality.         public DateTime ExchangeTime(TimeZoneInfo timeZone)         {             return TimeZoneInfo.ConvertTime(DateTime.Now, TimeZoneInfo.Local, timeZone);         }         ///          /// calculates the entry price for a long position         ///          ///          private double GetLongEntryPrice()         {             double entryPrice = 0;             // get previous candle high             double lastHigh = this.MarketSeries.High.Last(1);             // get pip distance from offset             double pipDistance = PipOffset * this.Symbol.PipSize;             // High of previous candle + 3 pips              entryPrice = lastHigh + pipDistance;             // round decimal places             entryPrice = Math.Round(entryPrice, Symbol.Digits);             return entryPrice;         }         ///          /// calculates the entry price for a short position         ///          ///          private double GetShortEntryPrice()         {             double entryPrice = 0;             // get previous candle high             double lastLow = this.MarketSeries.Low.Last(1);             // get pip distance from offset             double pipDistance = PipOffset * this.Symbol.PipSize;             // High of previous candle - 3 pips              entryPrice = lastLow - pipDistance;             // round decimal places             entryPrice = Math.Round(entryPrice, Symbol.Digits);             return entryPrice;         }         ///          ///          ///          ///          ///          private bool IsPositionOpenByType(TradeType type)         {             var p = Positions.FindAll(InstanceName, Symbol, type);             if (p.Count() >= 1)             {                 return true;             }             return false;         }         #endregion     } }