/// <summary>
        /// Will return the <see cref="SecurityCache"/> instance to use for a give Symbol.
        /// If the provided Symbol is a custom type which has an underlying we will try to use the
        /// underlying SecurityCache type cache, if the underlying is not present we will keep track
        /// of the custom Symbol in case it is added later.
        /// </summary>
        /// <returns>The cache instance to use</returns>
        public SecurityCache GetSecurityCache(Symbol symbol)
        {
            var securityCache = new SecurityCache();

            if (symbol.SecurityType == SecurityType.Base && symbol.HasUnderlying)
            {
                var underlyingSecurity = _securityProvider.GetSecurity(symbol.Underlying);
                if (underlyingSecurity != null)
                {
                    // we found the underlying, lets use its data type cache
                    SecurityCache.ShareTypeCacheInstance(underlyingSecurity.Cache, securityCache);
                }
                else
                {
                    // we didn't find the underlying, lets keep track of the underlying symbol which might get added in the future.
                    // else when it is added, we would have to go through existing Securities and find any which use it as underlying
                    _relatedSymbols.AddOrUpdate(symbol.Underlying,
                                                id => new ConcurrentBag <Symbol> {
                        symbol
                    },
                                                (id, bag) => { bag.Add(symbol); return(bag); }
                                                );
                }
            }
            else
            {
                ConcurrentBag <Symbol> customSymbols;
                if (_relatedSymbols.TryRemove(symbol, out customSymbols))
                {
                    // if we are here it means we added a symbol which is an underlying of some existing custom symbols
                    foreach (var customSymbol in customSymbols)
                    {
                        var customSecurity = _securityProvider.GetSecurity(customSymbol);
                        if (customSecurity != null)
                        {
                            // we make each existing custom security cache, use the new instance data type cache
                            // note that if any data already existed in the custom cache it will be passed
                            SecurityCache.ShareTypeCacheInstance(securityCache, customSecurity.Cache);
                        }
                    }
                }
            }

            return(securityCache);
        }
예제 #2
0
        private decimal GetTickerPrice(Order order)
        {
            var security    = _securityProvider.GetSecurity(order.Symbol);
            var tickerPrice = order.Direction == OrderDirection.Buy ? security.AskPrice : security.BidPrice;

            if (tickerPrice == 0)
            {
                var brokerageSymbol = _symbolMapper.GetBrokerageSymbol(order.Symbol);
                var tickers         = GetTickers();
                var ticker          = tickers.FirstOrDefault(t => t.Symbol == brokerageSymbol);
                if (ticker == null)
                {
                    throw new KeyNotFoundException($"BinanceBrokerage: Unable to resolve currency conversion pair: {order.Symbol}");
                }
                tickerPrice = ticker.Price;
            }
            return(tickerPrice);
        }
예제 #3
0
        /// <summary>
        /// Places a new order and assigns a new broker ID to the order
        /// </summary>
        /// <param name="order">The order to be placed</param>
        /// <returns>True if the request for a new order has been placed, false otherwise</returns>
        public override bool PlaceOrder(Order order)
        {
            var requestParams = new Dictionary <string, string>
            {
                { "instrument", _symbolMapper.GetBrokerageSymbol(order.Symbol) },
                { "units", Convert.ToInt32(order.AbsoluteQuantity).ToString() }
            };

            PopulateOrderRequestParameters(order, requestParams);

            var postOrderResponse = PostOrderAsync(requestParams);

            if (postOrderResponse == null)
            {
                return(false);
            }

            // if market order, find fill quantity and price
            var marketOrderFillPrice = 0m;

            if (order.Type == OrderType.Market)
            {
                marketOrderFillPrice = Convert.ToDecimal(postOrderResponse.price);
            }

            var marketOrderFillQuantity = 0;

            if (postOrderResponse.tradeOpened != null && postOrderResponse.tradeOpened.id > 0)
            {
                if (order.Type == OrderType.Market)
                {
                    marketOrderFillQuantity = postOrderResponse.tradeOpened.units;
                }
                else
                {
                    order.BrokerId.Add(postOrderResponse.tradeOpened.id.ToString());
                }
            }

            if (postOrderResponse.tradeReduced != null && postOrderResponse.tradeReduced.id > 0)
            {
                if (order.Type == OrderType.Market)
                {
                    marketOrderFillQuantity = postOrderResponse.tradeReduced.units;
                }
                else
                {
                    order.BrokerId.Add(postOrderResponse.tradeReduced.id.ToString());
                }
            }

            if (postOrderResponse.orderOpened != null && postOrderResponse.orderOpened.id > 0)
            {
                if (order.Type != OrderType.Market)
                {
                    order.BrokerId.Add(postOrderResponse.orderOpened.id.ToString());
                }
            }

            if (postOrderResponse.tradesClosed != null && postOrderResponse.tradesClosed.Count > 0)
            {
                marketOrderFillQuantity += postOrderResponse.tradesClosed
                                           .Where(trade => order.Type == OrderType.Market)
                                           .Sum(trade => trade.units);
            }

            // send Submitted order event
            const int orderFee = 0;

            order.PriceCurrency = _securityProvider.GetSecurity(order.Symbol).SymbolProperties.QuoteCurrency;
            OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, orderFee)
            {
                Status = OrderStatus.Submitted
            });

            if (order.Type == OrderType.Market)
            {
                // if market order, also send Filled order event
                OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, orderFee)
                {
                    Status       = OrderStatus.Filled,
                    FillPrice    = marketOrderFillPrice,
                    FillQuantity = marketOrderFillQuantity * Math.Sign(order.Quantity)
                });
            }

            return(true);
        }
예제 #4
0
        public static decimal GetHoldingsQuantity(this ISecurityProvider provider, Symbol symbol)
        {
            var security = provider.GetSecurity(symbol);

            return(security == null ? 0 : security.Holdings.Quantity);
        }