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);
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        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);
        }
Exemple #6
0
        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);
        }
Exemple #8
0
 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);
        }
Exemple #11
0
        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>();
 }
Exemple #13
0
        /// <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);
        }