Ejemplo n.º 1
0
        private BitfinexWebSocketWrapper SubscribeChannel(string channelName, Symbol symbol)
        {
            var channel = new Channel(channelName, symbol);

            var webSocket = GetFreeWebSocket(channel);

            webSocket.Send(JsonConvert.SerializeObject(new
            {
                @event  = "subscribe",
                channel = channelName,
                pair    = _symbolMapper.GetBrokerageSymbol(symbol)
            }));

            return(webSocket);
        }
Ejemplo n.º 2
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 parameters = new JsonObject
            {
                { "symbol", _symbolMapper.GetBrokerageSymbol(order.Symbol) },
                { "amount", order.Quantity.ToStringInvariant() },
                { "type", ConvertOrderType(_algorithm.BrokerageModel.AccountType, order.Type) },
                { "price", GetOrderPrice(order).ToStringInvariant() }
            };

            var orderProperties = order.Properties as BitfinexOrderProperties;

            if (orderProperties != null)
            {
                if (order.Type == OrderType.Limit)
                {
                    var flags = 0;
                    if (orderProperties.Hidden)
                    {
                        flags |= OrderFlags.Hidden;
                    }
                    if (orderProperties.PostOnly)
                    {
                        flags |= OrderFlags.PostOnly;
                    }

                    parameters.Add("flags", flags);
                }
            }

            var clientOrderId = GetNextClientOrderId();

            parameters.Add("cid", clientOrderId);

            _orderMap.TryAdd(clientOrderId, order);

            var obj = new JsonArray {
                0, "on", null, parameters
            };
            var json = JsonConvert.SerializeObject(obj);

            WebSocket.Send(json);

            return(true);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Gets the history for the requested security
        /// </summary>
        /// <param name="request">The historical data request</param>
        /// <returns>An enumerable of bars covering the span specified in the request</returns>
        public override IEnumerable <BaseData> GetHistory(Data.HistoryRequest request)
        {
            if (request.Resolution == Resolution.Tick || request.Resolution == Resolution.Second)
            {
                OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Warning, "InvalidResolution",
                                                    $"{request.Resolution} resolution not supported, no history returned"));
                yield break;
            }

            string resolution     = ConvertResolution(request.Resolution);
            long   resolutionInMS = (long)request.Resolution.ToTimeSpan().TotalMilliseconds;
            string symbol         = _symbolMapper.GetBrokerageSymbol(request.Symbol);
            long   startMTS       = (long)Time.DateTimeToUnixTimeStamp(request.StartTimeUtc) * 1000;
            long   endMTS         = (long)Time.DateTimeToUnixTimeStamp(request.EndTimeUtc) * 1000;
            string endpoint       = $"v2/candles/trade:{resolution}:t{symbol}/hist?limit=1000&sort=1";

            while ((endMTS - startMTS) > resolutionInMS)
            {
                var timeframe = $"&start={startMTS}&end={endMTS}";

                var restRequest = new RestRequest(endpoint + timeframe, Method.GET);
                var response    = ExecuteRestRequest(restRequest);

                if (response.StatusCode != HttpStatusCode.OK)
                {
                    throw new Exception($"BitfinexBrokerage.GetHistory: request failed: [{(int)response.StatusCode}] {response.StatusDescription}, Content: {response.Content}, ErrorMessage: {response.ErrorMessage}");
                }

                var candles = JsonConvert.DeserializeObject <object[][]>(response.Content)
                              .Select(entries => new Messages.Candle(entries))
                              .ToList();

                startMTS = candles.Last().Timestamp + resolutionInMS;
                var period = request.Resolution.ToTimeSpan();

                foreach (var candle in candles)
                {
                    yield return(new TradeBar()
                    {
                        Time = Time.UnixMillisecondTimeStampToDateTime(candle.Timestamp),
                        Symbol = request.Symbol,
                        Low = candle.Low,
                        High = candle.High,
                        Open = candle.Open,
                        Close = candle.Close,
                        Volume = candle.Volume,
                        Value = candle.Close,
                        DataType = MarketDataType.TradeBar,
                        Period = period,
                        EndTime = Time.UnixMillisecondTimeStampToDateTime(candle.Timestamp + (long)period.TotalMilliseconds)
                    });
                }
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Gets the history for the requested security
        /// </summary>
        /// <param name="request">The historical data request</param>
        /// <returns>An enumerable of bars covering the span specified in the request</returns>
        public override IEnumerable <BaseData> GetHistory(Data.HistoryRequest request)
        {
            if (request.Symbol.SecurityType != SecurityType.Crypto)
            {
                OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Warning, "InvalidSecurityType",
                                                    $"{request.Symbol.SecurityType} security type not supported, no history returned"));
                yield break;
            }

            if (request.Resolution == Resolution.Tick || request.Resolution == Resolution.Second)
            {
                OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Warning, "InvalidResolution",
                                                    $"{request.Resolution} resolution not supported, no history returned"));
                yield break;
            }

            if (request.StartTimeUtc >= request.EndTimeUtc)
            {
                OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Warning, "InvalidDateRange",
                                                    "The history request start date must precede the end date, no history returned"));
                yield break;
            }

            // if the end time cannot be rounded to resolution without a remainder
            if (request.EndTimeUtc.Ticks % request.Resolution.ToTimeSpan().Ticks > 0)
            {
                // give a warning and return
                OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Warning, "InvalidEndTime",
                                                    "The history request's end date is not a full multiple of a resolution. " +
                                                    "Bitfinex API only allows to support trade bar history requests. The start and end dates " +
                                                    "of a such request are expected to match exactly with the beginning of the first bar and ending of the last"));
                yield break;
            }

            string resolution       = ConvertResolution(request.Resolution);
            long   resolutionInMsec = (long)request.Resolution.ToTimeSpan().TotalMilliseconds;
            string symbol           = _symbolMapper.GetBrokerageSymbol(request.Symbol);
            long   startMsec        = (long)Time.DateTimeToUnixTimeStamp(request.StartTimeUtc) * 1000;
            long   endMsec          = (long)Time.DateTimeToUnixTimeStamp(request.EndTimeUtc) * 1000;
            string endpoint         = $"v2/candles/trade:{resolution}:t{symbol}/hist?limit=1000&sort=1";
            var    period           = request.Resolution.ToTimeSpan();

            do
            {
                var timeframe = $"&start={startMsec}&end={endMsec}";

                var restRequest = new RestRequest(endpoint + timeframe, Method.GET);
                var response    = ExecuteRestRequest(restRequest);

                if (response.StatusCode != HttpStatusCode.OK)
                {
                    throw new Exception(
                              $"BitfinexBrokerage.GetHistory: request failed: [{(int) response.StatusCode}] {response.StatusDescription}, " +
                              $"Content: {response.Content}, ErrorMessage: {response.ErrorMessage}");
                }

                // we need to drop the last bar provided by the exchange as its open time is a history request's end time
                var candles = JsonConvert.DeserializeObject <object[][]>(response.Content)
                              .Select(entries => new Messages.Candle(entries))
                              .Where(candle => candle.Timestamp != endMsec)
                              .ToList();

                // bitfinex exchange may return us an empty result - if we request data for a small time interval
                // during which no trades occurred - so it's rational to ensure 'candles' list is not empty before
                // we proceed to avoid an exception to be thrown
                if (candles.Any())
                {
                    startMsec = candles.Last().Timestamp + resolutionInMsec;
                }
                else
                {
                    OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Warning, "NoHistoricalData",
                                                        $"Exchange returned no data for {symbol} on history request " +
                                                        $"from {request.StartTimeUtc:s} to {request.EndTimeUtc:s}"));
                    yield break;
                }

                foreach (var candle in candles)
                {
                    yield return(new TradeBar()
                    {
                        Time = Time.UnixMillisecondTimeStampToDateTime(candle.Timestamp),
                        Symbol = request.Symbol,
                        Low = candle.Low,
                        High = candle.High,
                        Open = candle.Open,
                        Close = candle.Close,
                        Volume = candle.Volume,
                        Value = candle.Close,
                        DataType = MarketDataType.TradeBar,
                        Period = period,
                        EndTime = Time.UnixMillisecondTimeStampToDateTime(candle.Timestamp + (long)period.TotalMilliseconds)
                    });
                }
            } while (startMsec < endMsec);
        }