private Orderbook CalculateOrderbook(CrossRateCalcInfo info) { var sourceOrderbook1 = _orderbooks.GetValueOrDefault(info.Source1.Id); // ex: btcusd var sourceOrderbook2 = _orderbooks.GetValueOrDefault(info.Source2.Id); // ex: eurusd if (sourceOrderbook1 == null || sourceOrderbook2 == null) { var reason = "No orderbook for " + (sourceOrderbook1 == null ? info.Source1.Id : info.Source2.Id); Trace.Write(TraceLevelGroupEnum.WarnTrace, info.ResultingPairId, "Skipping generating cross-rate: " + reason, new { Event = "CrossRateSkipped", Reason = reason }); return(null); } var bestPrices1 = _bestPricesService.Calc(sourceOrderbook1); // ex: btcusd var bestPrices2 = _bestPricesService.Calc(sourceOrderbook2); // ex: eurusd var crossBid = GetCrossRate(bestPrices1, bestPrices2, info, true); var crossAsk = GetCrossRate(bestPrices1, bestPrices2, info, false); Trace.Write(TraceLevelGroupEnum.Trace, info.ResultingPairId, "Generating cross-rate", new { Event = "CrossRateGenerated", Bid = crossBid, Ask = crossAsk }); return(new Orderbook(info.ResultingPairId, ImmutableArray.Create(new OrderbookPosition(crossBid, 1)), // in future: calc whole orderbook ImmutableArray.Create(new OrderbookPosition(crossAsk, 1)))); }
private static decimal GetCrossRate(BestPrices bba1, BestPrices bba2, CrossRateCalcInfo info, bool bid) { var first = GetRate(bba1, bid, !info.Source1.IsTransitoryAssetQuoting); var second = GetRate(bba2, bid, info.Source2.IsTransitoryAssetQuoting); return(first * second); }
private CrossRateCalcInfoModel Convert([CanBeNull] CrossRateCalcInfo settings) { if (settings == null) { return(null); } return(_convertService.Convert <CrossRateCalcInfo, CrossRateCalcInfoModel>(settings)); }
public void IfSourceIsCrossRates_ShouldReturnCorrectResults() { //arrange var ethUsdCalcInfo = new CrossRateCalcInfo("ETHUSD", new CrossRateSourceAssetPair("ETHBTC", true), new CrossRateSourceAssetPair("BTCUSD", false)); var btcEurCalcInfo = new CrossRateCalcInfo("BTCEUR", new CrossRateSourceAssetPair("BTCUSD", true), new CrossRateSourceAssetPair("EURUSD", true)); var btcChfCalcInfo = new CrossRateCalcInfo("BTCCHF", new CrossRateSourceAssetPair("BTCUSD", true), new CrossRateSourceAssetPair("USDCHF", false)); var ethBtcOrderbook = MakeOrderbook("ETHBTC"); var eurUsdOrderbook = MakeOrderbook("EURUSD"); var usdChfOrderbook = MakeOrderbook("USDCHF"); var btcUsdOrderbook = MakeOrderbook("BTCUSD"); _testSuit .Setup <ICrossRateCalcInfosService>(s => s.GetDependentAssetPairs("ETHBTC") == new[] { ethUsdCalcInfo }) .Setup <ICrossRateCalcInfosService>(s => s.GetDependentAssetPairs("EURUSD") == new[] { btcEurCalcInfo }) .Setup <ICrossRateCalcInfosService>(s => s.GetDependentAssetPairs("USDCHF") == new[] { btcChfCalcInfo }) .Setup <ICrossRateCalcInfosService>(s => s.GetDependentAssetPairs("BTCUSD") == new[] { ethUsdCalcInfo, btcEurCalcInfo, btcChfCalcInfo }) .Setup <IBestPricesService>(s => s.Calc(ethBtcOrderbook) == new BestPrices(0.04m, 0.05m)) .Setup <IBestPricesService>(s => s.Calc(eurUsdOrderbook) == new BestPrices(1.2m, 1.3m)) .Setup <IBestPricesService>(s => s.Calc(usdChfOrderbook) == new BestPrices(0.98m, 0.99m)) .Setup <IBestPricesService>(s => s.Calc(btcUsdOrderbook) == new BestPrices(6500, 6600)) .Setup <IAssetPairSourceTypeService>(s => s.Get(It.IsNotNull <string>()) == AssetPairQuotesSourceTypeDomainEnum.CrossRates); //act var ethBtcResult = _testSuit.Sut.CalcDependentOrderbooks(ethBtcOrderbook); var eurUsdResult = _testSuit.Sut.CalcDependentOrderbooks(eurUsdOrderbook); var usdChfResult = _testSuit.Sut.CalcDependentOrderbooks(usdChfOrderbook); var btcUsdResult = _testSuit.Sut.CalcDependentOrderbooks(btcUsdOrderbook); //assert ethBtcResult.Should().BeEmpty(); eurUsdResult.Should().BeEmpty(); usdChfResult.Should().BeEmpty(); //BTCEUR = BTCUSD * (ask EURUSD)^-1 //BTCCHF = BTCUSD * USDCHF //ETHUSD = ETHBTC * BTCUSD btcUsdResult.Should().BeEquivalentTo( new[] { new Orderbook("BTCEUR", ImmutableArray.Create(new OrderbookPosition(6500 * (1 / 1.3m), 1)), ImmutableArray.Create(new OrderbookPosition(6600 * (1 / 1.2m), 1))), new Orderbook("BTCCHF", ImmutableArray.Create(new OrderbookPosition(6500 * 0.98m, 1)), ImmutableArray.Create(new OrderbookPosition(6600 * 0.99m, 1))), new Orderbook("ETHUSD", ImmutableArray.Create(new OrderbookPosition(0.04m * 6500, 1)), ImmutableArray.Create(new OrderbookPosition(0.05m * 6600, 1))), }); }
public AssetPairSettings(AssetPairQuotesSourceTypeDomainEnum quotesSourceType, AssetPairExtPriceSettings extPriceSettings, CrossRateCalcInfo crossRateCalcInfo, AggregateOrderbookSettings aggregateOrderbookSettings) { QuotesSourceType = quotesSourceType; ExtPriceSettings = extPriceSettings; CrossRateCalcInfo = crossRateCalcInfo; AggregateOrderbookSettings = aggregateOrderbookSettings; }
private void Validate(CrossRateCalcInfo crossRateCalcInfo) { crossRateCalcInfo.RequiredNotNull("crossRateCalcInfo for pair " + _assetPairId); crossRateCalcInfo.ResultingPairId.RequiredEqualsTo(_assetPairId, "crossRateCalcInfo.ResultingPairId for pair " + _assetPairId); Validate(crossRateCalcInfo.Source1); Validate(crossRateCalcInfo.Source2); crossRateCalcInfo.Source1.Id.RequiredNotEqualsTo(crossRateCalcInfo.Source2.Id, "crossRateCalcInfo.Source1.Id equals crossRateCalcInfo.Source2.Id for pair " + _assetPairId); }
public void IfSourceIsNotCrossRates_ShouldNotCalculateCrossRates() { //arrange var ethUsdCalcInfo = new CrossRateCalcInfo("ETHUSD", new CrossRateSourceAssetPair("ETHBTC", true), new CrossRateSourceAssetPair("BTCUSD", false)); var btcEurCalcInfo = new CrossRateCalcInfo("BTCEUR", new CrossRateSourceAssetPair("BTCUSD", true), new CrossRateSourceAssetPair("EURUSD", true)); var btcChfCalcInfo = new CrossRateCalcInfo("BTCCHF", new CrossRateSourceAssetPair("BTCUSD", true), new CrossRateSourceAssetPair("USDCHF", false)); var ethBtcOrderbook = MakeOrderbook("ETHBTC"); var eurUsdOrderbook = MakeOrderbook("EURUSD"); var usdChfOrderbook = MakeOrderbook("USDCHF"); var btcUsdOrderbook = MakeOrderbook("BTCUSD"); _testSuit .Setup <ICrossRateCalcInfosService>(s => s.GetDependentAssetPairs("ETHBTC") == new[] { ethUsdCalcInfo }) .Setup <ICrossRateCalcInfosService>(s => s.GetDependentAssetPairs("EURUSD") == new[] { btcEurCalcInfo }) .Setup <ICrossRateCalcInfosService>(s => s.GetDependentAssetPairs("USDCHF") == new[] { btcChfCalcInfo }) .Setup <ICrossRateCalcInfosService>(s => s.GetDependentAssetPairs("BTCUSD") == new[] { ethUsdCalcInfo, btcEurCalcInfo, btcChfCalcInfo }) .Setup <IAssetPairSourceTypeService>(s => s.Get(It.IsNotNull <string>()) == AssetPairQuotesSourceTypeDomainEnum.External); //act var ethBtcResult = _testSuit.Sut.CalcDependentOrderbooks(ethBtcOrderbook); var eurUsdResult = _testSuit.Sut.CalcDependentOrderbooks(eurUsdOrderbook); var usdChfResult = _testSuit.Sut.CalcDependentOrderbooks(usdChfOrderbook); var btcUsdResult = _testSuit.Sut.CalcDependentOrderbooks(btcUsdOrderbook); //assert ethBtcResult.Should().BeEmpty(); eurUsdResult.Should().BeEmpty(); usdChfResult.Should().BeEmpty(); btcUsdResult.Should().BeEmpty(); }
public void Update([NotNull] CrossRateCalcInfo info) { _settingsRootService.Update(info.ResultingPairId, old => new AssetPairSettings(old.QuotesSourceType, old.ExtPriceSettings, info, old.AggregateOrderbookSettings)); }
public AssetPairSettings(AssetPairQuotesSourceTypeDomainEnum quotesSourceType, AssetPairExtPriceSettings extPriceSettings, CrossRateCalcInfo crossRateCalcInfo) { QuotesSourceType = quotesSourceType; ExtPriceSettings = extPriceSettings; CrossRateCalcInfo = crossRateCalcInfo; }