public StrategyRunner(IBrokersCandlesService candleService, IMarketDetailsService marketDetailsService, IBroker broker, MarketDetails market) { _candleService = candleService; _marketDetailsService = marketDetailsService; _broker = broker; _market = market; }
public static decimal GetGBPPerPip( this IBrokersCandlesService candleService, IMarketDetailsService marketsService, IBroker broker, string market, decimal lotSize, DateTime date, bool updateCandles) { var marketDetails = marketsService.GetMarketDetails(broker.Name, market); decimal price = 0M; // If market contains GBP, then use the market for the price if (market.Contains("GBP")) { price = (decimal)candleService.GetLastClosedCandle(market, broker, Timeframe.D1, date, updateCandles).Value.OpenBid; if (market.StartsWith("GBP")) { price = 1M / price; } } else { // Try to get GBP candle, if it exists var marketForPrice = !market.Contains("/") ? $"GBP/{marketDetails.Currency}" : $"GBP/{market.Split('/')[1]}"; if (!marketsService.HasMarketDetails(broker.Name, marketForPrice)) { marketForPrice = $"{marketForPrice.Split('/')[1]}/{marketForPrice.Split('/')[0]}"; } if (marketForPrice == "GBP/GBP") { price = 1M; } else { // Get candle price, if it exists if (marketsService.HasMarketDetails(broker.Name, marketForPrice)) { price = (decimal)candleService.GetLastClosedCandle(marketForPrice, broker, Timeframe.D1, date, updateCandles).Value.OpenBid; } else { // Otherwise, try to get the USD candle and convert back to GBP // Try to get $ candle and convert to £ var usdCandle = candleService.GetLastClosedCandle($"USD/{market.Split('/')[1]}", broker, Timeframe.D1, date, updateCandles); var gbpUSDCandle = candleService.GetLastClosedCandle("GBP/USD", broker, Timeframe.D1, date, updateCandles); price = (decimal)gbpUSDCandle.Value.OpenBid / (decimal)usdCandle.Value.OpenBid; } } if (marketForPrice.StartsWith("GBP")) { price = 1M / price; } } return(lotSize * (decimal)marketDetails.ContractMultiplier * (decimal)marketDetails.PointSize * price); }
public bool UpdateAccount( IBrokerAccount account, IBrokersCandlesService candlesService, IMarketDetailsService marketsService, Action <string> updateProgressAction, out List <Trade> addedOrUpdatedTrades) { addedOrUpdatedTrades = new List <Trade>(); var limit = 500; foreach (var symbol in GetSymbols()) { Log.Debug($"Updating account for {symbol}"); // Get highest order ID var maxId = account.Trades.Count(t => t.CloseDateTime != null && t.Market == symbol) == 0 ? 1 : account.Trades .Where(t => t.CloseDateTime != null && t.Market == symbol) .Max(t => Convert.ToInt64(t.Id)); WebCallResult <IEnumerable <BinanceOrder> > orders = null; // Get orders while (orders == null || orders.Data.Count() == limit) { orders = _client.Spot.Order.GetAllOrders(symbol, orderId: maxId); if (orders.Success == false && orders.Error.Code == -1003) { Log.Info("Too many Binance requests - pausing requests"); // -1003 = Too many requests Thread.Sleep(60 * 1000); orders = null; continue; } if (orders.Success) { AddOrUpdateOrders(account, addedOrUpdatedTrades, orders); } else { Log.Error($"Unable to get orders for symbol {symbol} - {orders.Error.Message}"); break; } maxId = account.Trades.Count(t => t.CloseDateTime != null && t.Market == symbol) == 0 ? 1 : account.Trades .Where(t => t.CloseDateTime != null && t.Market == symbol) .Max(t => Convert.ToInt64(t.Id)); } } Log.Info($"Binance account updated - {addedOrUpdatedTrades} trades added or updated"); return(true); }
public static decimal GetOnePipInDecimals(this IMarketDetailsService marketsService, string broker, string market) { if (marketsService == null) { return(0M); } var marketDetails = marketsService.GetMarketDetails(broker, market); return(marketDetails.PointSize.Value); }
public void UpdateBrokerAccount( IBroker broker, IBrokersCandlesService candleService, IMarketDetailsService marketsService, ITradeDetailsAutoCalculatorService tradeCalculateService, UpdateOption option = UpdateOption.OnlyIfNotRecentlyUpdated) { void UpdateProgressAction(string txt) { } UpdateBrokerAccount(broker, candleService, marketsService, tradeCalculateService, UpdateProgressAction, option); }
public void UpdateBrokerAccount( IBroker broker, IBrokersCandlesService candleService, IMarketDetailsService marketsService, ITradeDetailsAutoCalculatorService tradeCalculateService, Action <string> updateProgressAction, UpdateOption option = UpdateOption.OnlyIfNotRecentlyUpdated) { if (option == UpdateOption.OnlyIfNotRecentlyUpdated && (AccountLastUpdated != null && (DateTime.UtcNow - AccountLastUpdated.Value).TotalHours < 24)) { return; } Log.Debug($"Updating {broker.Name} account"); foreach (var t in Trades) { tradeCalculateService.RemoveTrade(t); } try { broker.UpdateAccount(this, candleService, marketsService, updateProgressAction, out var addedOrUpdatedTrades); foreach (var trade in addedOrUpdatedTrades) { RecalculateTrade(trade, candleService, marketsService, broker); } } catch (Exception ex) { Log.Error("Unable to update account", ex); MessageBox.Show($"Unable to update account - {ex.Message}", "Unable to update account", MessageBoxButtons.OK); } AccountLastUpdated = DateTime.UtcNow; Log.Debug($"Completed updating {broker.Name} trades"); _brokerAccountUpdatedSubject.OnNext(new BrokerAccountUpdated(this)); }
public static decimal GetProfitForLatestDay(this Trade trade, IBrokersCandlesService candlesService, IBrokersService brokersService, IMarketDetailsService marketDetailsService) { var broker = brokersService.Brokers.FirstOrDefault(x => x.Name == trade.Broker); if (broker != null) { var marketDetails = marketDetailsService.GetMarketDetails(broker.Name, trade.Market); var now = DateTime.UtcNow; var endDate = trade.CloseDateTime != null ? new DateTime(trade.CloseDateTime.Value.Year, trade.CloseDateTime.Value.Month, trade.CloseDateTime.Value.Day, 23, 59, 59, DateTimeKind.Utc) : new DateTime(now.Year, now.Month, now.Day, 23, 59, 59, DateTimeKind.Utc); var startDate = new DateTime(endDate.Year, endDate.Month, endDate.Day, 0, 0, 0, DateTimeKind.Utc); return(trade.GetTradeProfit(endDate, Basics.Timeframe.D1, candlesService, marketDetails, broker, false) - trade.GetTradeProfit(startDate, Basics.Timeframe.D1, candlesService, marketDetails, broker, false)); } return(decimal.MinValue); }
public bool UpdateAccount(IBrokerAccount account, IBrokersCandlesService candlesService, IMarketDetailsService marketsService, Action <string> updateProgressAction, out List <Trade> addedOrUpdatedTrades) { throw new NotImplementedException(); }
public static List <Trade> Run( Type strategyType, Func <bool> stopFunc, IBrokersCandlesService candlesService, IMarketDetailsService marketDetailsService, IBroker broker, int threads) { var stopwatch = Stopwatch.StartNew(); var strategyMarket = new Dictionary <string, StrategyBase>(); var completed = 0; var trades = new List <Trade>(); var producerConsumer = new ProducerConsumer <(Type StrategyType, MarketDetails Market)>( threads, d => { if (stopFunc?.Invoke() ?? false) { return(ProducerConsumerActionResult.Stop); } var strategyTester = new StrategyRunner(candlesService, marketDetailsService, broker, d.Market); var strategy = StrategyHelper.CreateStrategyInstance(d.StrategyType); lock (strategyMarket) { strategyMarket[d.Market.Name] = strategy; } var marketTrades = strategyTester.Run(strategy, stopFunc, strategy.StartTime, strategy.EndTime); if (marketTrades != null) { lock (trades) { trades.AddRange(marketTrades); } // _results.AddResult(result); // Adding trades to UI in realtime slows down the UI too much with strategies with many trades completed++; Log.Info($"Completed {completed}/{strategy.Markets.Length}"); } return(ProducerConsumerActionResult.Success); }); foreach (var market in StrategyHelper.GetStrategyMarkets(strategyType)) { producerConsumer.Add((strategyType, marketDetailsService.GetMarketDetails(broker.Name, market))); } producerConsumer.Start(); producerConsumer.SetProducerCompleted(); producerConsumer.WaitUntilConsumersFinished(); //var trades = _results.Results.ToList(); // Set trade profits var balance = 10000M; foreach (var t in trades.OrderBy(z => z.OrderDateTime ?? z.EntryDateTime)) { var riskAmount = (strategyMarket[t.Market].RiskEquityPercent / 100M) * balance; var profit = t.RMultiple * riskAmount ?? 0M; t.NetProfitLoss = profit; t.RiskAmount = riskAmount; balance += profit; if (balance < 0) { balance = 0M; } } stopwatch.Stop(); Log.Info($"Simulation run completed in {stopwatch.Elapsed.TotalSeconds}s"); return(trades); }
public static decimal GetPriceFromPips(this IMarketDetailsService marketsService, string brokerName, decimal pips, string market) { var pipInDecimals = marketsService.GetOnePipInDecimals(brokerName, market); return(pips * pipInDecimals); }
public void RecalculateTrade(Trade trade, IBrokersCandlesService candleService, IMarketDetailsService marketsService, IBroker broker) { // Update price per pip if (trade.EntryQuantity != null && trade.EntryDateTime != null) { trade.PricePerPip = candleService.GetGBPPerPip(marketsService, broker, trade.Market, trade.EntryQuantity.Value, trade.EntryDateTime.Value, true); } // Update risk if (trade.InitialStopInPips == null || trade.PricePerPip == null) { trade.RiskPercentOfBalance = null; trade.RiskAmount = null; trade.RiskPercentOfBalance = null; } else { trade.RiskAmount = trade.PricePerPip.Value * trade.InitialStopInPips.Value; var balance = GetBalance(trade.StartDateTime); if (balance != 0.0M) { var startTime = trade.OrderDateTime ?? trade.EntryDateTime; trade.RiskPercentOfBalance = (trade.RiskAmount * 100M) / GetBalance(startTime); } else { trade.RiskPercentOfBalance = null; } } }
static TradeCalculator() { _candlesService = DependencyContainer.Container.GetExportedValue <IBrokersCandlesService>(); _brokersService = DependencyContainer.Container.GetExportedValue <IBrokersService>(); _marketsService = DependencyContainer.Container.GetExportedValue <IMarketDetailsService>(); }
/// <summary> /// For most currency pairs, the 'pip' location is the fourth decimal place. In this example, if the GBP/USD moved from 1.42279 to 1.42289 you would have gained or lost one pip /// http://help.fxcm.com/markets/Trading/Education/Trading-Basics/32856512/How-to-calculate-PIP-value.htm /// </summary> /// <param name="price"></param> /// <returns></returns> public static decimal GetPriceInPips(this IMarketDetailsService marketsService, string brokerName, decimal price, string market) { var pipInDecimals = marketsService.GetOnePipInDecimals(brokerName, market); return(pipInDecimals != 0M ? price / pipInDecimals : 0); }