public void Check_Account_Calculations_Correct() { var position1 = TestObjectsFactory.CreateOpenedPosition("EURUSD", Accounts[0], MarginTradingTestsUtils.TradingConditionId, 1000, 1.02M); _ordersCache.Positions.Add(position1); position1.UpdateClosePrice(1.04M); position1.GetFpl(); var account = _accountsCacheService.Get(position1.AccountId); Assert.IsNotNull(account); Assert.AreEqual(1000, account.Balance); Assert.AreEqual(20, Math.Round(account.GetPnl(), 5)); Assert.AreEqual(1020, account.GetTotalCapital()); Assert.AreEqual(6.8M, account.GetUsedMargin()); Assert.AreEqual(1009.8M, account.GetMarginAvailable()); Assert.AreEqual(150M, account.GetMarginUsageLevel()); var position2 = TestObjectsFactory.CreateOpenedPosition("EURUSD", Accounts[0], MarginTradingTestsUtils.TradingConditionId, -30000, 1.02M); _ordersCache.Positions.Add(position2); position2.UpdateClosePrice(1.04M); position2.GetFpl(); Assert.IsNotNull(account); Assert.AreEqual(1000, account.Balance); Assert.AreEqual(-580, Math.Round(account.GetPnl(), 5)); Assert.AreEqual(420, Math.Round(account.GetTotalCapital(), 5)); Assert.AreEqual(214.8m, account.GetUsedMargin()); Assert.AreEqual(97.8m, Math.Round(account.GetMarginAvailable(), 5)); Assert.AreEqual(1.95531m, Math.Round(account.GetMarginUsageLevel(), 5)); }
public void Is_Fpl_Buy_Cross_Correct() { const string instrument = "BTCCHF"; _bestPriceConsumer.SendEvent(this, new BestPriceChangeEventArgs(new InstrumentBidAskPair { Instrument = "USDCHF", Ask = 1.072030M, Bid = 1.071940M })); _bestPriceConsumer.SendEvent(this, new BestPriceChangeEventArgs(new InstrumentBidAskPair { Instrument = "BTCUSD", Ask = 1001M, Bid = 1000M })); _bestPriceConsumer.SendEvent(this, new BestPriceChangeEventArgs(new InstrumentBidAskPair { Instrument = "BTCCHF", Ask = 901M, Bid = 900M })); _fxRateCacheService.SetQuote(new InstrumentBidAskPair { Instrument = "USDCHF", Ask = 1.072030M, Bid = 1.071940M }); _fxRateCacheService.SetQuote(new InstrumentBidAskPair { Instrument = "BTCUSD", Ask = 1001M, Bid = 1000M }); _fxRateCacheService.SetQuote(new InstrumentBidAskPair { Instrument = "BTCCHF", Ask = 901M, Bid = 900M }); var position = TestObjectsFactory.CreateOpenedPosition(instrument, Accounts[0], MarginTradingTestsUtils.TradingConditionId, 1000, 935.461M, 0.932888034778M); position.UpdateClosePrice(935.61M); Assert.AreEqual(139m, Math.Round(position.GetFpl(), 3)); }
public void Check_Position_PnL() { _bestPriceConsumer.SendEvent(this, new BestPriceChangeEventArgs( new InstrumentBidAskPair { Instrument = "EURUSD", Ask = 1.25M, Bid = 1.15M })); _bestPriceConsumer.SendEvent(this, new BestPriceChangeEventArgs( new InstrumentBidAskPair { Instrument = "CHFJPY", Ask = 6.036M, Bid = 1.9M })); _fxRateCacheService.SetQuote(new InstrumentBidAskPair { Instrument = "EURUSD", Ask = 9000M, Bid = 9000M }); _fxRateCacheService.SetQuote(new InstrumentBidAskPair { Instrument = "EURJPY", Ask = 0.83M, Bid = 0.83M }); var position1 = TestObjectsFactory.CreateOpenedPosition("EURUSD", Accounts[1], MarginTradingTestsUtils.TradingConditionId, 15000, 1.3M, 0.0001111111111111M); position1.UpdateClosePrice(1.15M); var position2 = TestObjectsFactory.CreateOpenedPosition("CHFJPY", Accounts[1], MarginTradingTestsUtils.TradingConditionId, -23, 1.96M, 1.204819277108M); position2.UpdateClosePrice(6.036M); Assert.AreEqual(-0.25M, position1.GetFpl()); Assert.AreEqual(-112.94939759M, position2.GetFpl()); }
public void Check_Calculations_As_In_Excel_Document() { Accounts[0].Balance = 50000; _accountsCacheService.UpdateAccountBalance(Accounts[0].Id, Accounts[0].Balance, DateTime.UtcNow); _bestPriceConsumer.SendEvent(this, new BestPriceChangeEventArgs(new InstrumentBidAskPair { Instrument = "EURUSD", Ask = 1.061M, Bid = 1.06M })); _bestPriceConsumer.SendEvent(this, new BestPriceChangeEventArgs(new InstrumentBidAskPair { Instrument = "BTCEUR", Ask = 1092M, Bid = 1091M })); _bestPriceConsumer.SendEvent(this, new BestPriceChangeEventArgs(new InstrumentBidAskPair { Instrument = "BTCUSD", Ask = 1001M, Bid = 1000M })); _fxRateCacheService.SetQuote(new InstrumentBidAskPair { Instrument = "EURUSD", Ask = 1.061M, Bid = 1.06M }); _fxRateCacheService.SetQuote(new InstrumentBidAskPair { Instrument = "BTCEUR", Ask = 1092M, Bid = 1091M }); _fxRateCacheService.SetQuote(new InstrumentBidAskPair { Instrument = "BTCUSD", Ask = 1001M, Bid = 1000M }); var positions = new List <Position> { TestObjectsFactory.CreateOpenedPosition("EURUSD", Accounts[0], MarginTradingTestsUtils.TradingConditionId, 100000, 1.05M), TestObjectsFactory.CreateOpenedPosition("EURUSD", Accounts[0], MarginTradingTestsUtils.TradingConditionId, -200000, 1.04M), TestObjectsFactory.CreateOpenedPosition("EURUSD", Accounts[0], MarginTradingTestsUtils.TradingConditionId, 50000, 1.061M), TestObjectsFactory.CreateOpenedPosition("BTCEUR", Accounts[0], MarginTradingTestsUtils.TradingConditionId, 100, 1120, 1.06m) }; foreach (var position in positions) { _ordersCache.Positions.Add(position); } positions[0].UpdateClosePrice(1.06M); positions[1].UpdateClosePrice(1.061M); positions[2].UpdateClosePrice(1.06M); positions[3].UpdateClosePrice(1091M); var account = Accounts[0]; Assert.AreEqual(50000, account.Balance); Assert.AreEqual(43676.000, Math.Round(account.GetTotalCapital(), 5)); Assert.AreEqual(33484.3M, Math.Round(account.GetFreeMargin(), 1)); Assert.AreEqual(28388.5M, Math.Round(account.GetMarginAvailable(), 1)); Assert.AreEqual(-6324.000, Math.Round(account.GetPnl(), 5)); Assert.AreEqual(10191.7M, Math.Round(account.GetUsedMargin(), 1)); Assert.AreEqual(15287.5M, Math.Round(account.GetMarginInit(), 1)); }
public void Check_Account_StopOut_Level() { var position1 = TestObjectsFactory.CreateOpenedPosition("EURUSD", Accounts[0], MarginTradingTestsUtils.TradingConditionId, 130000, 1.02M); _ordersCache.Positions.Add(position1); position1.UpdateClosePrice(1.02M); position1.GetFpl(); var account = _accountsCacheService.Get(position1.AccountId); Assert.IsNotNull(account); Assert.IsTrue(account.GetMarginUsageLevel() <= 1.25M); }
public void Is_Fpl_Sell_Correct() { const string instrument = "BTCUSD"; _bestPriceConsumer.SendEvent(this, new BestPriceChangeEventArgs(new InstrumentBidAskPair { Instrument = instrument, Ask = 800, Bid = 790 })); var position = TestObjectsFactory.CreateOpenedPosition(instrument, Accounts[0], MarginTradingTestsUtils.TradingConditionId, -10, 790); position.UpdateClosePrice(800); Assert.AreEqual(-100, position.GetFpl()); }
public async Task Check_Position_PnL_Multi_Thread() { _bestPriceConsumer.SendEvent(this, new BestPriceChangeEventArgs( new InstrumentBidAskPair { Instrument = "BTCUSD", Ask = 2M, Bid = 1M })); _fxRateCacheService.SetQuote(new InstrumentBidAskPair { Instrument = "EURUSD", Ask = 1, Bid = 1 }); var position1 = TestObjectsFactory.CreateOpenedPosition("BTCUSD", Accounts[1], MarginTradingTestsUtils.TradingConditionId, 1, 2M, 1M); var updateFxTask = new Action(() => { position1.UpdateCloseFxPrice(2); }); var getPnLTask = new Action(() => { position1.GetFpl(); }); var wrong = 0; const int attempts = 100000; for (int i = 0; i < attempts; i++) { position1.UpdateClosePrice(1M); await Task.WhenAll(Task.Factory.StartNew(getPnLTask), Task.Factory.StartNew(updateFxTask)); var pnl = position1.GetFpl(); if (pnl != -2) { wrong++; } position1.UpdateClosePrice(2M); position1.UpdateCloseFxPrice(1); Assert.AreEqual(0, position1.GetFpl()); } Assert.AreEqual(0, wrong, $"Number of wrong P&L calculations from {attempts} attempts"); }
public void Check_Position_Margin() { _bestPriceConsumer.SendEvent(this, new BestPriceChangeEventArgs( new InstrumentBidAskPair { Instrument = "EURUSD", Ask = 1.3M, Bid = 1.2M })); _bestPriceConsumer.SendEvent(this, new BestPriceChangeEventArgs( new InstrumentBidAskPair { Instrument = "CHFJPY", Ask = 2.5M, Bid = 2.3M })); _fxRateCacheService.SetQuote(new InstrumentBidAskPair { Instrument = "EURUSD", Ask = 9000M, Bid = 9000M }); _fxRateCacheService.SetQuote(new InstrumentBidAskPair { Instrument = "EURJPY", Ask = 2.3M, Bid = 2.3M }); var position1 = TestObjectsFactory.CreateOpenedPosition("EURUSD", Accounts[1], MarginTradingTestsUtils.TradingConditionId, 15000, 1.3M, 1 / 9000M); position1.UpdateClosePrice(1.2M); position1.UpdateCloseFxPrice(1 / 9000M); var position2 = TestObjectsFactory.CreateOpenedPosition("CHFJPY", Accounts[1], MarginTradingTestsUtils.TradingConditionId, -100, 2.3M, 1 / 2.3M); position2.UpdateClosePrice(2.5M); position2.UpdateCloseFxPrice(1 / 2.3M); Assert.AreEqual(0.02M, position1.GetMarginInit()); Assert.AreEqual(0.01M, position1.GetMarginMaintenance()); Assert.AreEqual(10.87, position2.GetMarginInit()); Assert.AreEqual(7.25M, position2.GetMarginMaintenance()); }
public void Is_Summary_Volume_Ivalid(decimal volume, bool isValid) { const string instrument = "BTCUSD"; var quote = new InstrumentBidAskPair { Instrument = instrument, Bid = 1.55M, Ask = 1.57M }; _bestPriceConsumer.SendEvent(this, new BestPriceChangeEventArgs(quote)); var existingLong = TestObjectsFactory.CreateOpenedPosition(instrument, Accounts[0], MarginTradingTestsUtils.TradingConditionId, 110, 1.57M); var existingShort = TestObjectsFactory.CreateOpenedPosition(instrument, Accounts[0], MarginTradingTestsUtils.TradingConditionId, -12, 1.55M); var existingOtherAcc = TestObjectsFactory.CreateOpenedPosition(instrument, Accounts[1], MarginTradingTestsUtils.TradingConditionId, 49, 1.57M); _ordersCache.Positions.Add(existingLong); _ordersCache.Positions.Add(existingShort); _ordersCache.Positions.Add(existingOtherAcc); var order = TestObjectsFactory.CreateNewOrder(OrderType.Market, instrument, Accounts[0], MarginTradingTestsUtils.TradingConditionId, volume); if (isValid) { Assert.DoesNotThrow(() => _validateOrderService.MakePreTradeValidation(order, true, _me)); } else { var ex = Assert.Throws <ValidateOrderException>(() => _validateOrderService.MakePreTradeValidation(order, true, _me)); Assert.That(ex.RejectReason == OrderRejectReason.MaxPositionLimit); } }