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; } } }
public static List <Candle> GetDerivedCandles(this IBrokersCandlesService candlesService, IBroker broker, string firstSymbol, string secondSymbol, Timeframe timeframe, bool updateCandles = false, DateTime?minOpenTimeUtc = null, DateTime?maxCloseTimeUtc = null, bool forceCreateDerived = false) { var pair = $"{firstSymbol}{secondSymbol}"; if (!forceCreateDerived) { var candles = candlesService.GetCandles(broker, pair, timeframe, false, minOpenTimeUtc: minOpenTimeUtc, maxCloseTimeUtc: maxCloseTimeUtc); if (candles != null && candles.Count > 0) { return(candles); } } var calculatedMarketCandles = new DerivedMarketCandles(broker, candlesService); return(calculatedMarketCandles.CreateCandlesSeries( firstSymbol, secondSymbol, timeframe, updateCandles, minOpenTimeUtc, maxCloseTimeUtc)); }
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); }
/// <summary> /// Uses a faster mechanism for finding candles. /// </summary> /// <param name="service"></param> /// <param name="market"></param> /// <param name="broker"></param> /// <param name="timeframe"></param> /// <param name="dateTime"></param> /// <param name="updateCandles"></param> /// <returns></returns> public static Candle?GetLastClosedCandle(this IBrokersCandlesService service, string market, IBroker broker, Timeframe timeframe, DateTime dateTime, bool updateCandles = false) { var candles = service.GetCandles(broker, market, timeframe, updateCandles); if (candles == null || candles.Count == 0) { return(null); } var maxItemsInRange = 20; if (candles.Count <= maxItemsInRange) { for (var i = candles.Count - 1; i >= 0; i--) { if (candles[i].CloseTimeTicks <= dateTime.Ticks) { return(candles[i]); } } return(null); } if (candles[candles.Count - 1].CloseTimeTicks <= dateTime.Ticks) { return(candles[candles.Count - 1]); } var range1Start = 0; var range2End = candles.Count - 1; var range1End = (range2End - range1Start) / 2; while (range2End - range1Start + 1 > maxItemsInRange) { var range2Start = range1End + 1; if (candles[range2Start].CloseTimeTicks > dateTime.Ticks) { range2End = range1End; range1End = range1Start + (range2End - range1Start) / 2; } else { range1Start = range1End + 1; range1End = range1Start + (range2End - range1Start) / 2; } } for (var i = range2End; i >= range1Start; i--) { if (candles[i].CloseTimeTicks <= dateTime.Ticks) { return(candles[i]); } } return(null); }
public StrategyRunner( IBrokersCandlesService candleService, IBroker broker, IBrokersService brokersService) { _candleService = candleService; _broker = broker; _brokersService = brokersService; }
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 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 ConvertCandles(IBrokersCandlesService candlesService, IBroker broker, List <string> markets) { var candlesDirectory = Path.Combine(Path.GetDirectoryName(typeof(MainWindowViewModel).Assembly.Location), "Candles"); if (!Directory.Exists(candlesDirectory)) { Directory.CreateDirectory(candlesDirectory); } foreach (var market in markets) { if (File.Exists(GetCandlesPath(market, Timeframe.H2)) && File.Exists(GetCandlesPath(market, Timeframe.H4)) && File.Exists(GetCandlesPath(market, Timeframe.D1)) && File.Exists(GetCandlesPath(market, Timeframe.M5))) { continue; } var allM5Candles = candlesService.GetCandles(broker, market, Timeframe.M5, false, cacheData: false); var allH2Candles = candlesService.GetCandles(broker, market, Timeframe.H2, false, cacheData: false); var allH4Candles = candlesService.GetCandles(broker, market, Timeframe.H4, false, cacheData: false); var allD1Candles = candlesService.GetCandles(broker, market, Timeframe.D1, false, cacheData: false); if (allD1Candles.Count == 0 || allH2Candles.Count == 0 || allH4Candles.Count == 0 || allM5Candles.Count == 0) { continue; } var bytes = Compress(BrokersCandlesService.CandlesToBytes(allM5Candles)); var path = Path.Combine(candlesDirectory, $"{market.Replace("/", string.Empty)}_M5.dat"); File.WriteAllBytes(path, bytes); bytes = Compress(BrokersCandlesService.CandlesToBytes(allH2Candles)); path = Path.Combine(candlesDirectory, $"{market.Replace("/", string.Empty)}_H2.dat"); File.WriteAllBytes(path, bytes); bytes = Compress(BrokersCandlesService.CandlesToBytes(allH4Candles)); path = Path.Combine(candlesDirectory, $"{market.Replace("/", string.Empty)}_H4.dat"); File.WriteAllBytes(path, bytes); bytes = Compress(BrokersCandlesService.CandlesToBytes(allD1Candles)); path = Path.Combine(candlesDirectory, $"{market.Replace("/", string.Empty)}_D1.dat"); File.WriteAllBytes(path, bytes); GC.Collect(); } }
public Trainer(IBrokersCandlesService candlesService, IBrokersService brokersService) { _candlesService = candlesService; _brokersService = brokersService; _dataGenerator = new DataGenerator(_candlesService, _brokersService); ManualResetEvent dispatcherReadyEvent = new ManualResetEvent(false); new Thread(new ThreadStart(() => { _modelDispatcher = Dispatcher.CurrentDispatcher; dispatcherReadyEvent.Set(); Dispatcher.Run(); })).Start(); dispatcherReadyEvent.WaitOne(); }
/// <summary> /// Uses a faster mechanism for finding candles. /// </summary> /// <param name="service"></param> /// <param name="market"></param> /// <param name="broker"></param> /// <param name="timeframe"></param> /// <param name="dateTime"></param> /// <param name="updateCandles"></param> /// <returns></returns> public static Candle?GetLastClosedCandle(this IBrokersCandlesService service, string market, IBroker broker, Timeframe timeframe, DateTime dateTime, bool updateCandles = false) { var candles = service.GetCandles(broker, market, timeframe, updateCandles); if (candles == null || candles.Count == 0) { return(null); } var index = candles.BinarySearchGetItem( i => candles[i].CloseTimeTicks, 0, dateTime.Ticks, BinarySearchMethod.PrevLowerValueOrValue); if (index != -1) { return(candles[index]); } return(null); }
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 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 GetTradeProfit(this Trade trade, DateTime dateTimeUTC, Timeframe candlesTimeframe, IBrokersCandlesService candlesService, MarketDetails marketDetails, IBroker broker, bool updateCandles) { if (trade.EntryPrice == null || trade.EntryDateTime == null) { return(0M); } if (trade.CloseDateTime != null && trade.CloseDateTime.Value <= dateTimeUTC) { return(trade.Profit ?? 0M); } if (trade.EntryDateTime >= dateTimeUTC) { return(0M); } var latestCandle = candlesService.GetLastClosedCandle( trade.Market, broker, candlesTimeframe, dateTimeUTC, updateCandles); if (latestCandle != null && trade.PricePerPip != null) { var closePriceToUse = trade.TradeDirection == TradeDirection.Long ? (decimal)latestCandle.Value.CloseBid : (decimal)latestCandle.Value.CloseAsk; var profitPips = PipsHelper.GetPriceInPips(trade.TradeDirection == TradeDirection.Long ? closePriceToUse - trade.EntryPrice.Value : trade.EntryPrice.Value - closePriceToUse, marketDetails); var totalRunningTime = (DateTime.UtcNow - trade.EntryDateTime.Value).TotalDays; var runningTime = (trade.EntryDateTime.Value - dateTimeUTC).TotalDays; var tradeProfit = trade.PricePerPip.Value * profitPips + (!totalRunningTime.Equals(0.0) && trade.Rollover != null ? trade.Rollover.Value * (decimal)(runningTime / totalRunningTime) : 0M); return(tradeProfit); } return(0M); }
public static void UpdateCandles(IBroker broker, IBrokersCandlesService candlesService, IEnumerable <string> markets, IEnumerable <Timeframe> timeframes, int threads = 3, Action <string> updateProgressAction = null) { var completed = 0; var total = 0; var producerConsumer = new ProducerConsumer <(string Market, Timeframe Timeframe)>(threads, d => { Log.Info($"Updating {d.Data.Timeframe} candles for {d.Data.Market}"); candlesService.UpdateCandles(broker, d.Data.Market, d.Data.Timeframe); candlesService.UnloadCandles(d.Data.Market, d.Data.Timeframe, broker); Log.Info($"Updated {d.Data.Timeframe} candles for {d.Data.Market}"); Interlocked.Increment(ref completed); updateProgressAction?.Invoke($"Updated {completed}/{total} markets/timeframes"); return(ProducerConsumerActionResult.Success); }); foreach (var market in markets) { foreach (var timeframe in timeframes) { total++; producerConsumer.Add((market, timeframe)); } } updateProgressAction?.Invoke($"Updating {total} markets/timeframes"); producerConsumer.SetProducerCompleted(); producerConsumer.Start(); producerConsumer.WaitUntilConsumersFinished(); Log.Info("Updated FX candles"); }
public DerivedMarketCandles(IBroker broker, IBrokersCandlesService candlesService) { _broker = broker; _candlesService = candlesService; }
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 List <(DateTime Time, decimal Value)> GetDailyTotalNetMoneyIn(IBroker broker, BrokerAccount account, IBrokersCandlesService candlesService) { var ret = new List <(DateTime Time, decimal Value)>(); /*for (var date = new DateTime(2018, 1, 1); date <= DateTime.UtcNow; date = date.AddDays(1)) * { * var netMoneyIn = 0.0M; * foreach (var depositWithdrawal in account.DepositsWithdrawals.Where(x => x.Time <= date)) * { * netMoneyIn += CryptoValueHelper.GetAssetUsdValue(candlesService, broker, depositWithdrawal.Asset, depositWithdrawal.Time, depositWithdrawal.Amount); * } * * ret.Add((date, netMoneyIn)); * }*/ return(ret); }
public DataGenerator(IBrokersCandlesService candlesService, IBrokersService brokersService) { _candlesService = candlesService; _brokersService = brokersService; }
public static List <(DateTime Time, decimal Value)> GetDailyTotalValues(IBroker broker, BrokerAccount account, IBrokersCandlesService candlesService) { var ret = new List <(DateTime Time, decimal Value)>(); /*var now = DateTime.UtcNow; * * for (var date = new DateTime(2018, 1, 1); date <= now; date = date.AddDays(1)) * { * var assetBalances = account.GetAssetBalances(broker, candlesService, date); * * if (date == now) * { * } * * // Convert to USDs * var value = 0.0M; * foreach (var assetBalance in assetBalances) * { * value += CryptoValueHelper.GetAssetUsdValue(candlesService, broker, assetBalance.Asset, date, assetBalance.Amount); * } * * ret.Add((date, value)); * }*/ return(ret); }
public CryptoTransactionsUSDTCalculator(IBrokersCandlesService candlesService, IBroker binanceBroker) { _candlesService = candlesService; _binanceBroker = binanceBroker; }
public MLDataWriter(IBroker broker, IBrokersCandlesService candlesService) { _broker = broker; _candlesService = candlesService; }
static TradeCalculator() { _candlesService = DependencyContainer.Container.GetExportedValue <IBrokersCandlesService>(); _brokersService = DependencyContainer.Container.GetExportedValue <IBrokersService>(); _marketsService = DependencyContainer.Container.GetExportedValue <IMarketDetailsService>(); }
public static List <Candle> GetCandlesUptoSpecificTime(this IBrokersCandlesService brokerCandles, IBroker broker, string market, Timeframe timeframe, bool updateCandles, DateTime?startUtc, DateTime?endUtc, Timeframe smallestTimeframeForPartialCandle = Timeframe.M1) { var allLargeChartCandles = brokerCandles.GetCandles(broker, market, timeframe, updateCandles, cacheData: false, minOpenTimeUtc: startUtc, maxCloseTimeUtc: endUtc); var smallestTimeframeCandles = brokerCandles.GetCandles(broker, market, smallestTimeframeForPartialCandle, updateCandles, cacheData: false, maxCloseTimeUtc: endUtc); var largeChartCandles = new List <Candle>(); var endTicks = endUtc?.Ticks ?? -1; var endTimeTicks = endUtc?.Ticks; // Add complete candle for (var i = 0; i < allLargeChartCandles.Count; i++) { var currentCandle = allLargeChartCandles[i]; if (endTimeTicks == null || currentCandle.CloseTimeTicks <= endTimeTicks) { largeChartCandles.Add(currentCandle); } } // Add incomplete candle var latestCandleTimeTicks = largeChartCandles[largeChartCandles.Count - 1].CloseTimeTicks; float?openBid = null, closeBid = null, highBid = null, lowBid = null; float?openAsk = null, closeAsk = null, highAsk = null, lowAsk = null; long? openTimeTicks = null, closeTimeTicks = null; foreach (var smallestTimeframeCandle in smallestTimeframeCandles) { if (smallestTimeframeCandle.OpenTimeTicks >= latestCandleTimeTicks && (smallestTimeframeCandle.CloseTimeTicks <= endTicks || endTicks == -1)) { if (openTimeTicks == null) { openTimeTicks = smallestTimeframeCandle.OpenTimeTicks; } if (openBid == null || smallestTimeframeCandle.OpenBid < openBid) { openBid = smallestTimeframeCandle.OpenBid; } if (highBid == null || smallestTimeframeCandle.HighBid > highBid) { highBid = smallestTimeframeCandle.HighBid; } if (lowBid == null || smallestTimeframeCandle.LowBid < lowBid) { lowBid = smallestTimeframeCandle.LowBid; } closeBid = smallestTimeframeCandle.CloseBid; if (openAsk == null || smallestTimeframeCandle.OpenAsk < openAsk) { openAsk = smallestTimeframeCandle.OpenAsk; } if (highAsk == null || smallestTimeframeCandle.HighAsk > highAsk) { highAsk = smallestTimeframeCandle.HighAsk; } if (lowAsk == null || smallestTimeframeCandle.LowAsk < lowAsk) { lowAsk = smallestTimeframeCandle.LowAsk; } closeAsk = smallestTimeframeCandle.CloseAsk; closeTimeTicks = smallestTimeframeCandle.CloseTimeTicks; } if (smallestTimeframeCandle.CloseTime() > endUtc) { break; } } if (openBid != null) { largeChartCandles.Add(new Candle { OpenBid = openBid.Value, CloseBid = closeBid.Value, HighBid = highBid.Value, LowBid = lowBid.Value, OpenAsk = openAsk.Value, CloseAsk = closeAsk.Value, HighAsk = highAsk.Value, LowAsk = lowAsk.Value, CloseTimeTicks = closeTimeTicks.Value, OpenTimeTicks = openTimeTicks.Value, IsComplete = 0 }); } return(largeChartCandles); }