public Order?DecideOrder(PositionDelta delta)
        {
            OptionQuote quote = delta.Quote ?? MarketDataClient.GetOptionQuote(delta.Symbol);

            // TODO: Remove after testing
            //Log.Warning("Not getting real quote");
            //OptionQuote quote = new OptionQuote(delta.Symbol, delta.Price * (float).99, delta.Price * (float)1.01, delta.Price, delta.Price * (float)1.06, (float)1.0);

            if (quote.Time < DateTime.Now.AddSeconds(-15))
            {
                Log.Information("Getting new quote. Old quote- {@Quote}", quote);
                quote = MarketDataClient.GetOptionQuote(delta.Symbol);
            }
            Log.Information("{DeltaType} delta {@Delta}- current mark price {Mark}. Symbol {Symbol}", delta.DeltaType, delta, quote.Mark.ToString("0.00"), delta.Symbol);

            Position?currentPos = BrokerClient.GetPosition(delta.Symbol);

            if (delta.DeltaType == DeltaType.SELL)
            {
                return(DecideSell(delta, currentPos));
            }
            else if (delta.DeltaType == DeltaType.ADD ||
                     delta.DeltaType == DeltaType.NEW)
            {
                return(DecideBuy(delta, currentPos, quote));
            }
            else
            {
                Log.Error("Unrecognized deltaType: {type}", delta.DeltaType);
                return(null);
            }
        }
        public async Task <List <object> > GetOptionChain(string symbol)
        {
            if (symbol == null)
            {
                throw new ArgumentNullException("symbols");
            }

            var quotes = new List <object>();

            var url = "/v1/marketdata/chains?" +
                      "symbol=" + symbol + "&includeQuotes=true";
            var text = await this.http.GetStringAsync(url);

            OptionQuote optionChain = JsonConvert.DeserializeObject <OptionQuote>(text);

            foreach (var optionDate in optionChain.callExpDateMap.Keys)
            {
                DateTime date = DateTime.ParseExact(optionDate.Substring(0, 10), "yyyy-MM-dd", null);

                foreach (var strikeArr in optionChain.callExpDateMap[optionDate].Values)
                {
                    foreach (var strike in strikeArr)
                    {
                        try
                        {
                            strike.ExpirationDate = date;
                            strike.Underlyer      = symbol;
                            quotes.Add(strike);
                        } catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                            Console.WriteLine(ex.InnerException?.Message);
                        }
                    }
                }
            }

            return(quotes);
        }
Example #3
0
        public override OptionQuote GetOptionQuote(string symbol)
        {
            if (!OptionSymbolUtils.IsOptionSymbol(symbol))
            {
                throw new ArgumentException("Provided symbol is not an option symbol: " + symbol);
            }
            string tdAmSymbol = OptionSymbolUtils.ConvertDateFormat(symbol, OptionSymbolUtils.StandardDateFormat, Constants.TDOptionDateFormat);

            RestClient    client   = new RestClient("https://api.tdameritrade.com/v1/marketdata/" + tdAmSymbol + "/quotes");
            RestRequest   request  = CreateRequest(Method.GET);
            IRestResponse response = ExecuteRequest(client, request);

            if (!response.IsSuccessful || response.Content.Contains("Symbol not found"))
            {
                throw new MarketDataException("Get quote unsuccessful for symbol " + symbol);
            }
            Regex       responseRegex = new Regex("{\"assetType.*?}");
            Match       match         = responseRegex.Match(response.Content);
            OptionQuote quote         = JsonConvert.DeserializeObject <TDOptionQuote>(match.Value);

            return(quote);
        }
 protected override Position InstantiateWithSymbolOverride(string overrideSymbol, OptionQuote quote)
 {
     return(new Position(overrideSymbol, Quantity, (float)Average));
 }
 protected override FilledOrder InstantiateWithSymbolOverride(string overrideSymbol, OptionQuote quote)
 {
     return(new FilledOrder(overrideSymbol, (float)FilledPrice, Instruction, OrderType, (float)Limit, Quantity, Time, quote));
 }
        private Order?DecideBuy(PositionDelta delta, Position?currentPos, OptionQuote quote)
        {
            if (delta.DeltaType == DeltaType.ADD && currentPos == null)
            {
                Log.Information("No current position corresponding to {DeltaType} delta {@Delta}. Symbol {Symbol}", delta.DeltaType, delta, delta.Symbol);
            }
            else if (delta.DeltaType == DeltaType.NEW && currentPos != null)
            {
                Log.Warning("Current position exists {@CurrentPosition} for {DeltaType} delta {@Delta}. Taking no action for Symbol {Symbol}", currentPos, delta.DeltaType, delta, delta.Symbol);
                return(null);
            }

            if (delta.Age.TotalMinutes > _config.MinutesUntilBuyOrderExpires)
            {
                Log.Warning("New/Add delta expired after {Minutes} minutes for delta {@Delta}. Symbol {Symbol}", delta.Age.TotalMinutes.ToString("0"), delta, delta.Symbol);
                return(null);
            }

            if (delta.Price > _config.MaxBuyPrice)
            {
                Log.Information("Buy price higher than buy max limit. Skipping order. Symbol {Symbol}, Price={Price}", delta.Symbol, delta.Price);
                return(null);
            }

            float diff                = quote.Mark - delta.Price;
            float absPercent          = Math.Abs(diff / delta.Price);
            bool  withinHighThreshold = Math.Sign(diff) >= 0 && absPercent <= _config.HighBuyThreshold;
            bool  withinLowThreshold  = Math.Sign(diff) <= 0 && absPercent <= _config.LowBuyThreshold;

            int    quantity;
            string orderType;
            float  limit = -1;

            if (withinHighThreshold && _config.HighBuyStrategy == BuyStrategyType.MARKET ||
                withinLowThreshold && _config.LowBuyStrategy == BuyStrategyType.MARKET)
            {
                orderType = OrderType.MARKET;
                quantity  = DecideBuyQuantity(quote.AskPrice, delta, currentPos, quote.AskPrice); // Assume we will pay the ask price
            }
            else if (withinHighThreshold && _config.HighBuyStrategy == BuyStrategyType.DELTA_LIMIT ||
                     withinLowThreshold && _config.LowBuyStrategy == BuyStrategyType.DELTA_LIMIT)
            {
                orderType = OrderType.LIMIT;
                limit     = delta.Price;
                quantity  = DecideBuyQuantity(limit, delta, currentPos, quote.AskPrice);
            }
            else if (withinHighThreshold && _config.HighBuyStrategy == BuyStrategyType.THRESHOLD_LIMIT)
            {
                orderType = OrderType.LIMIT;
                limit     = delta.Price * (1 + _config.HighBuyLimit);
                quantity  = DecideBuyQuantity(limit, delta, currentPos, quote.AskPrice);
            }
            else if (withinLowThreshold && _config.LowBuyStrategy == BuyStrategyType.THRESHOLD_LIMIT)
            {
                orderType = OrderType.LIMIT;
                limit     = delta.Price * (1 - _config.LowBuyLimit);
                quantity  = DecideBuyQuantity(limit, delta, currentPos, quote.AskPrice);
            }
            else
            {
                Log.Information("Current mark price not within buy threshold. Skipping order. Symbol {Symbol}, Mark={Mark}", delta.Symbol, quote.Mark.ToString("0.00"));
                return(null);
            }

            if (quantity == 0)
            {
                Log.Information("Decided buy quantity of 0. Skipping Order. Symbol {Symbol}, CurrentPosition = {@CurrentPosition}, Delta = {@Delta}",
                                delta.Symbol, currentPos, delta);
                return(null);
            }
            else
            {
                DateTime cancelTime = delta.Time.Date.Equals(DateTime.Today)
                    ? delta.Time.AddMinutes(_config.MinutesUntilBuyOrderExpires)
                    : DateTime.Now.AddMinutes(_config.MinutesUntilBuyOrderExpires);

                Order order = new Order(delta.Symbol, quantity, InstructionType.BUY_TO_OPEN, orderType, limit, cancelTime);
                Log.Information("Decided new Order: {@Order} for Symbol {Symbol}", order, order.Symbol);
                return(order);
            }
        }