Example #1
0
        /// <summary>
        /// Filter orders that are already calculated
        /// </summary>
        /// <returns></returns>
        private List <Order> GetOrdersForCalculation()
        {
            //read orders synchronously
            var openOrders = _orderReader.GetActive();

            //prepare the list of orders
            var lastInvocationTime = CalcLastInvocationTime();
            var calculatedIds      = _overnightSwapCache.GetAll().Where(x => x.IsSuccess && x.Time >= lastInvocationTime)
                                     .Select(x => x.OpenOrderId).ToHashSet();
            //select only non-calculated orders, changed before current invocation time
            var filteredOrders =
                openOrders.Where(x => !calculatedIds.Contains(x.Id) && x.OpenDate <= lastInvocationTime).ToList();

            //detect orders for which last calculation failed and it was closed
            var failedClosedOrders = _overnightSwapHistoryRepository.GetAsync(lastInvocationTime, _currentStartTimestamp)
                                     .GetAwaiter().GetResult()
                                     .Where(x => !x.IsSuccess).Select(x => x.OpenOrderId)
                                     .Except(openOrders.Select(y => y.Id)).ToList();

            if (failedClosedOrders.Any())
            {
                _log.WriteErrorAsync(nameof(OvernightSwapService), nameof(GetOrdersForCalculation), new Exception(
                                         $"Overnight swap calculation failed for some orders and they were closed before recalculation: {string.Join(", ", failedClosedOrders)}."),
                                     DateTime.UtcNow).GetAwaiter().GetResult();
            }

            return(filteredOrders);
        }
Example #2
0
        public async Task OvernightSwapCalculation_Success()
        {
            _bestPriceConsumer.SendEvent(this,
                                         new BestPriceChangeEventArgs(new InstrumentBidAskPair {
                Instrument = "BTCUSD", Bid = 9000M, Ask = 9010M
            }));

            await _accountAssetsRepository.AddOrReplaceAsync(new AccountAssetPair
            {
                TradingConditionId  = MarginTradingTestsUtils.TradingConditionId,
                BaseAssetId         = "USD",
                Instrument          = "BTCUSD",
                LeverageInit        = 100,
                LeverageMaintenance = 150,
                SwapLong            = 100,
                SwapShort           = 100,
                OvernightSwapLong   = 1,
                OvernightSwapShort  = 1
            });

            await _accountAssetsManager.UpdateAccountAssetsCache();

            var accountId = (await _fakeMarginTradingAccountsRepository.GetAllAsync("1"))
                            .First(x => x.ClientId == "1" && x.BaseAssetId == "USD").Id;

            _ordersCache.ActiveOrders.Add(new Order
            {
                Id                 = "1",
                AccountId          = accountId,
                Instrument         = "BTCUSD",
                ClientId           = "1",
                TradingConditionId = "1",
                AccountAssetId     = "USD",
                Volume             = 1,
                OpenDate           = new DateTime(2017, 01, 01, 20, 50, 0),
                CloseDate          = new DateTime(2017, 01, 02, 20, 50, 0),
                MatchedOrders      = new MatchedOrderCollection(new List <MatchedOrder> {
                    new MatchedOrder()
                    {
                        Volume = 1
                    }
                }),
                LegalEntity = "LYKKETEST",
            });

            var accountBalance = (await _fakeMarginTradingAccountsRepository.GetAsync(accountId)).Balance;

            _overnightSwapService.CalculateAndChargeSwaps();

            var calc = _overnightSwapCache.GetAll().First();

            Assert.AreEqual(24.68493151M, calc.Value);
            Assert.True(calc.IsSuccess);
            Assert.AreEqual(accountBalance - 24.68493151M, (await _fakeMarginTradingAccountsRepository.GetAsync(accountId)).Balance);
        }
Example #3
0
        /// <summary>
        /// Filter orders that are already calculated
        /// </summary>
        /// <returns></returns>
        private IEnumerable <Order> GetOrdersForCalculation()
        {
            //read orders syncronously
            var openOrders = _orderReader.GetActive();

            //prepare the list of orders
            var lastInvocationTime = CalcLastInvocationTime;
            var lastCalculation    = _overnightSwapCache.GetAll().Where(x => x.Time > lastInvocationTime).ToList();
            var calculatedIds      = lastCalculation.Where(x => x.IsSuccess).SelectMany(x => x.OpenOrderIds).ToHashSet();
            var filteredOrders     = openOrders.Where(x => !calculatedIds.Contains(x.Id));

            //detect orders for which last calculation failed and it was closed
            var failedClosedOrders = lastCalculation.Where(x => !x.IsSuccess).SelectMany(x => x.OpenOrderIds)
                                     .Except(openOrders.Select(y => y.Id)).ToList();

            if (failedClosedOrders.Any())
            {
                _log.WriteErrorAsync(nameof(OvernightSwapService), nameof(GetOrdersForCalculation), new Exception(
                                         $"Overnight swap calculation failed for some orders and they were closed before recalculation: {string.Join(", ", failedClosedOrders)}."),
                                     DateTime.UtcNow).GetAwaiter().GetResult();
            }

            return(filteredOrders);
        }
Example #4
0
        public async Task OvernightSwapCalculation_Success()
        {
            var dsMock = Mock.Get(Container.Resolve <IDateService>());

            dsMock.Setup(d => d.Now()).Returns(new DateTime(2017, 1, 2));

            await _accountAssetsRepository.AddOrReplaceAsync(new AccountAssetPair
            {
                TradingConditionId  = MarginTradingTestsUtils.TradingConditionId,
                BaseAssetId         = "USD",
                Instrument          = "BTCUSD",
                LeverageInit        = 100,
                LeverageMaintenance = 150,
                SwapLong            = 100,
                SwapShort           = 100,
                OvernightSwapLong   = 1,
                OvernightSwapShort  = 1
            });

            await _accountAssetsManager.UpdateAccountAssetsCache();

            var accountId = (await _fakeMarginTradingAccountsRepository.GetAllAsync("1"))
                            .First(x => x.ClientId == "1" && x.BaseAssetId == "USD").Id;

            _ordersCache.ActiveOrders.Add(new Order
            {
                Id                 = "1",
                AccountId          = accountId,
                Instrument         = "BTCUSD",
                ClientId           = "1",
                TradingConditionId = "1",
                AccountAssetId     = "USD",
                Volume             = 1,
                OpenDate           = new DateTime(2017, 01, 01, 20, 50, 0),
                MatchedOrders      = new MatchedOrderCollection(new List <MatchedOrder> {
                    new MatchedOrder()
                    {
                        Volume = 1
                    }
                }),
                LegalEntity = "LYKKETEST",
            });

            _ordersCache.ActiveOrders.Add(new Order
            {
                Id                 = "2",
                AccountId          = accountId,
                Instrument         = "BTCUSD",
                ClientId           = "1",
                TradingConditionId = "1",
                AccountAssetId     = "USD",
                Volume             = 1,
                OpenDate           = new DateTime(2017, 01, 02, 20, 50, 0),
                MatchedOrders      = new MatchedOrderCollection(new List <MatchedOrder> {
                    new MatchedOrder()
                    {
                        Volume = 1
                    }
                }),
                LegalEntity = "LYKKETEST",
            });

            const decimal swapValue = 0.00273973M;

            var initialAccountBalance = (await _fakeMarginTradingAccountsRepository.GetAsync(accountId)).Balance;

            _overnightSwapService.CalculateAndChargeSwaps();

            var calculations = _overnightSwapCache.GetAll();

            Assert.AreEqual(1, calculations.Count);             //only order 1 should be calculated
            var singleCalc = calculations.First();

            Assert.AreEqual(swapValue, singleCalc.Value);
            Assert.True(singleCalc.IsSuccess);
            Assert.AreEqual(initialAccountBalance - swapValue, (await _fakeMarginTradingAccountsRepository.GetAsync(accountId)).Balance);

            //move few hours later and calculate again
            dsMock.Setup(d => d.Now()).Returns(new DateTime(2017, 1, 2, 2, 0, 0));

            //nothing should change
            calculations = _overnightSwapCache.GetAll();
            Assert.AreEqual(1, calculations.Count);
            Assert.AreEqual(initialAccountBalance - swapValue, (await _fakeMarginTradingAccountsRepository.GetAsync(accountId)).Balance);

            _overnightSwapService.CalculateAndChargeSwaps();

            //move to next day and calculate again
            dsMock.Setup(d => d.Now()).Returns(new DateTime(2017, 1, 3));

            _overnightSwapService.CalculateAndChargeSwaps();

            calculations = _overnightSwapCache.GetAll();
            Assert.AreEqual(2, calculations.Count);             // both order 1 and order 2 should be calculated
            Assert.AreEqual(initialAccountBalance - swapValue * 3,
                            (await _fakeMarginTradingAccountsRepository.GetAsync(accountId)).Balance);
        }