public async Task CreateLimitOrderAsync(string assetId, string exchange, LimitOrderType limitOrderType,
                                                decimal price, decimal volume, string userId)
        {
            AssetHedgeSettings assetHedgeSettings =
                await _assetHedgeSettingsService.GetByAssetIdAsync(assetId, exchange);

            if (assetHedgeSettings == null)
            {
                throw new InvalidOperationException("Asset hedge settings not found");
            }

            if (assetHedgeSettings.Mode != AssetHedgeMode.Manual)
            {
                throw new InvalidOperationException("Asset hedge settings mode should be 'Manual'");
            }

            if (!_exchangeAdapters.TryGetValue(assetHedgeSettings.Exchange, out IExchangeAdapter exchangeAdapter))
            {
                throw new InvalidOperationException("There is no exchange provider");
            }

            HedgeLimitOrder hedgeLimitOrder = HedgeLimitOrder.Create(assetHedgeSettings.Exchange,
                                                                     assetHedgeSettings.AssetId, assetHedgeSettings.AssetPairId, limitOrderType, PriceType.Limit, price,
                                                                     volume);

            hedgeLimitOrder.Context = new { price, volume, userId }.ToJson();

            _log.InfoWithDetails("Manual hedge limit order created", new { hedgeLimitOrder, userId });

            await exchangeAdapter.ExecuteLimitOrderAsync(hedgeLimitOrder);
        }
 public LimitOrder(decimal price, decimal volume, LimitOrderType type)
 {
     Id     = Guid.NewGuid().ToString("D");
     Price  = price;
     Volume = volume;
     Type   = type;
 }
 private static LimitOrder Create(decimal price, decimal volume, LimitOrderType type)
 => new LimitOrder
 {
     Id     = Guid.NewGuid().ToString("D"),
     Price  = price,
     Volume = volume,
     Type   = type
 };
예제 #4
0
 public PlacedOrderReport(Guid id, long orderBookUpdateReportId, LimitOrderType type, decimal price, decimal volume, decimal levelMarkup)
 {
     Id = id;
     OrderBookUpdateReportId = orderBookUpdateReportId;
     Type        = type;
     Price       = price;
     Volume      = volume;
     LevelMarkup = levelMarkup;
 }
        public async Task ClosePositionAsync(string assetId, string exchange, string userId)
        {
            Position position = await _positionService.GetByAssetIdAsync(assetId, exchange);

            if (position == null)
            {
                throw new InvalidOperationException("Position not found");
            }

            AssetHedgeSettings assetHedgeSettings =
                await _assetHedgeSettingsService.GetByAssetIdAsync(assetId, exchange);

            if (assetHedgeSettings == null)
            {
                throw new InvalidOperationException("Asset hedge settings not found");
            }

            if (assetHedgeSettings.Mode == AssetHedgeMode.Auto)
            {
                throw new InvalidOperationException("Can not close position while asset hedge settings mode is 'Auto'");
            }

            if (!_exchangeAdapters.TryGetValue(assetHedgeSettings.Exchange, out IExchangeAdapter exchangeAdapter))
            {
                throw new InvalidOperationException("There is no exchange provider");
            }

            Quote quote = _quoteService.GetByAssetPairId(assetHedgeSettings.Exchange,
                                                         assetHedgeSettings.AssetPairId);

            if (quote == null)
            {
                throw new InvalidOperationException("No quote");
            }

            LimitOrderType limitOrderType = position.Volume > 0
                ? LimitOrderType.Sell
                : LimitOrderType.Buy;

            decimal price = limitOrderType == LimitOrderType.Sell
                ? quote.Ask
                : quote.Bid;

            decimal volume = Math.Abs(position.Volume);

            HedgeLimitOrder hedgeLimitOrder = HedgeLimitOrder.Create(assetHedgeSettings.Exchange,
                                                                     assetHedgeSettings.AssetId, assetHedgeSettings.AssetPairId, limitOrderType, PriceType.Limit, price,
                                                                     volume);

            hedgeLimitOrder.Context = new { userId }.ToJson();

            _log.InfoWithDetails("Manual hedge limit order created to closed position", new { hedgeLimitOrder, userId });

            await exchangeAdapter.ExecuteLimitOrderAsync(hedgeLimitOrder);
        }
예제 #6
0
 public LimitOrderCreateModel(Guid?id, string assetPair, decimal price, decimal volume,
                              ulong accountId, ulong walletId, LimitOrderType type, bool cancelPrevious)
 {
     Id             = id;
     AssetPair      = assetPair;
     Price          = price;
     Volume         = volume;
     AccountId      = accountId;
     WalletId       = walletId;
     Type           = type;
     CancelPrevious = cancelPrevious;
 }
 public InternalOrder(string walletId, string assetPairId, LimitOrderType type, decimal price, decimal volume,
                      bool fullExecution)
     : this()
 {
     WalletId      = walletId;
     AssetPairId   = assetPairId;
     Type          = type;
     Price         = price;
     Volume        = volume;
     FullExecution = fullExecution;
     Status        = InternalOrderStatus.New;
     CreatedDate   = DateTime.UtcNow;
 }
        public static OrderAction ToOrderAction(this LimitOrderType limitOrderType)
        {
            if (limitOrderType == LimitOrderType.Buy)
            {
                return(OrderAction.Buy);
            }

            if (limitOrderType == LimitOrderType.Sell)
            {
                return(OrderAction.Sell);
            }

            throw new InvalidEnumArgumentException(nameof(limitOrderType), (int)limitOrderType, typeof(TradeType));
        }
 public static HedgeLimitOrder Create(string exchange, string assetId, string assetPairId,
                                      LimitOrderType limitOrderType, PriceType priceType, decimal price, decimal volume)
 {
     return(new HedgeLimitOrder
     {
         Id = Guid.NewGuid().ToString("D"),
         Exchange = exchange,
         AssetId = assetId,
         AssetPairId = assetPairId,
         Type = limitOrderType,
         PriceType = priceType,
         Timestamp = DateTime.UtcNow,
         Price = price,
         Volume = volume
     });
 }
        private async Task <IReadOnlyCollection <HedgeLimitOrder> > CreateLimitOrdersAsync(
            IEnumerable <AssetInvestment> assetInvestments)
        {
            HedgeSettings hedgeSettings = await _hedgeSettingsService.GetAsync();

            var hedgeLimitOrders = new List <HedgeLimitOrder>();

            foreach (AssetInvestment assetInvestment in assetInvestments)
            {
                AssetHedgeSettings assetHedgeSettings =
                    await _assetHedgeSettingsService.EnsureAsync(assetInvestment.AssetId);

                LimitOrderType limitOrderType = assetInvestment.RemainingAmount > 0
                    ? LimitOrderType.Sell
                    : LimitOrderType.Buy;

                if (!CanCreateHedgeLimitOrder(assetInvestment, assetHedgeSettings, hedgeSettings, limitOrderType))
                {
                    continue;
                }

                decimal commonThresholdUp = limitOrderType == LimitOrderType.Buy
                    ? hedgeSettings.ThresholdUpBuy
                    : hedgeSettings.ThresholdUpSell;

                LimitOrderPrice limitOrderPrice = LimitOrderPriceCalculator.Calculate(assetInvestment.Quote,
                                                                                      Math.Abs(assetInvestment.RemainingAmount), limitOrderType,
                                                                                      assetHedgeSettings.ThresholdUp ?? commonThresholdUp, hedgeSettings.MarketOrderMarkup);

                decimal price = limitOrderPrice.Price;

                decimal volume = Math.Abs(assetInvestment.RemainingAmount / assetInvestment.Quote.Mid);

                HedgeLimitOrder hedgeLimitOrder = HedgeLimitOrder.Create(assetHedgeSettings.Exchange,
                                                                         assetHedgeSettings.AssetId, assetHedgeSettings.AssetPairId, limitOrderType, limitOrderPrice.Type,
                                                                         price, volume);

                hedgeLimitOrder.Context = assetInvestment.ToJson();

                hedgeLimitOrders.Add(hedgeLimitOrder);
            }

            return(hedgeLimitOrders);
        }
예제 #11
0
        public static LimitOrderPrice Calculate(Quote quote, decimal volume, LimitOrderType limitOrderType,
                                                decimal thresholdUp, decimal marketOrderMarkup)
        {
            if (volume < thresholdUp)
            {
                decimal price = limitOrderType == LimitOrderType.Sell
                    ? quote.Ask
                    : quote.Bid;

                return(new LimitOrderPrice(price, PriceType.Limit));
            }
            else
            {
                decimal price = limitOrderType == LimitOrderType.Sell
                    ? quote.Bid * (1 - marketOrderMarkup)
                    : quote.Ask * (1 + marketOrderMarkup);

                return(new LimitOrderPrice(price, PriceType.Market));
            }
        }
        public void Calculate_Buy_Limit_Price()
        {
            // arrange

            var quote = new Quote("BTCUSD", DateTime.UtcNow, 6000, 5000, "source");

            decimal volume = 2000;

            LimitOrderType limitOrderType = LimitOrderType.Buy;

            decimal thresholdUp       = 5000;
            decimal marketOrderMarkup = .1m;

            // act

            LimitOrderPrice limitOrderPrice =
                LimitOrderPriceCalculator.Calculate(quote, volume, limitOrderType, thresholdUp, marketOrderMarkup);

            // assert

            Assert.IsTrue(limitOrderPrice.Price == quote.Bid && limitOrderPrice.Type == PriceType.Limit);
        }
 public Task <ExternalTrade> ExecuteLimitOrderAsync(string assetPairId, decimal volume, decimal price,
                                                    LimitOrderType limitOrderType)
 => ExecuteLimitOrderAsync(assetPairId, volume, price,
                           limitOrderType == LimitOrderType.Sell ? Side.Sell : Side.Buy);
        private static bool CanCreateHedgeLimitOrder(AssetInvestment assetInvestment,
                                                     AssetHedgeSettings assetHedgeSettings, HedgeSettings hedgeSettings, LimitOrderType limitOrderType)
        {
            if (assetInvestment.IsDisabled)
            {
                return(false);
            }

            decimal absoluteRemainingAmount = Math.Abs(assetInvestment.RemainingAmount);

            if (absoluteRemainingAmount <= 0)
            {
                return(false);
            }

            decimal thresholdCritical = assetHedgeSettings.ThresholdCritical ?? hedgeSettings.ThresholdCritical;

            if (0 < thresholdCritical && thresholdCritical <= absoluteRemainingAmount)
            {
                return(false);
            }

            decimal commonThresholdDown = limitOrderType == LimitOrderType.Buy ? hedgeSettings.ThresholdDownBuy : hedgeSettings.ThresholdDownSell;

            decimal thresholdDown = assetHedgeSettings.ThresholdDown ?? commonThresholdDown;

            if (assetHedgeSettings.Exchange != ExchangeNames.Virtual && absoluteRemainingAmount < thresholdDown)
            {
                return(false);
            }

            if (assetHedgeSettings.Mode != AssetHedgeMode.Auto && assetHedgeSettings.Mode != AssetHedgeMode.Idle)
            {
                return(false);
            }

            if (assetInvestment.Quote == null)
            {
                return(false);
            }

            return(true);
        }
        public async Task <string> CreateOrderAsync(string walletId, string assetPairId, LimitOrderType type,
                                                    decimal price, decimal volume, bool fullExecution)
        {
            var internalOrder = new InternalOrder(walletId, assetPairId, type, price, volume, fullExecution);

            await _internalOrderRepository.InsertAsync(internalOrder);

            return(internalOrder.Id);
        }