Exemplo n.º 1
0
        /// <summary>
        /// Parses a contract for future with malformed data.
        /// Malformed data usually manifests itself by having "0" assigned to some values
        /// we expect, like the contract's expiry date. The contract is returned by IB
        /// like this, usually due to a high amount of data subscriptions that are active
        /// in an account, surpassing IB's imposed limit. Read more about this here: https://interactivebrokers.github.io/tws-api/rtd_fqa_errors.html#rtd_common_errors_maxmktdata
        ///
        /// We are provided a string in the Symbol in malformed contracts that can be
        /// parsed to construct the clean contract, which is done by this method.
        /// </summary>
        /// <param name="malformedContract">Malformed contract (for futures), i.e. a contract with invalid values ("0") in some of its fields</param>
        /// <param name="symbolPropertiesDatabase">The symbol properties database to use</param>
        /// <returns>Clean Contract for the future</returns>
        /// <remarks>
        /// The malformed contract returns data similar to the following when calling <see cref="InteractiveBrokersBrokerage.GetContractDetails"/>: ES       MAR2021
        /// </remarks>
        public Contract ParseMalformedContractFutureSymbol(Contract malformedContract, SymbolPropertiesDatabase symbolPropertiesDatabase)
        {
            Log.Trace($"InteractiveBrokersSymbolMapper.ParseMalformedContractFutureSymbol(): Parsing malformed contract: {InteractiveBrokersBrokerage.GetContractDescription(malformedContract)} with trading class: \"{malformedContract.TradingClass}\"");

            // capture any character except spaces, match spaces, capture any char except digits, capture digits
            var matches = Regex.Matches(malformedContract.Symbol, @"^(\S*)\s*(\D*)(\d*)");

            var match                   = matches[0].Groups;
            var contractSymbol          = match[1].Value;
            var contractMonthExpiration = DateTime.ParseExact(match[2].Value, "MMM", CultureInfo.CurrentCulture).Month;
            var contractYearExpiration  = match[3].Value;

            var    leanSymbol = GetLeanRootSymbol(contractSymbol);
            string market;

            if (!symbolPropertiesDatabase.TryGetMarket(leanSymbol, SecurityType.Future, out market))
            {
                market = InteractiveBrokersBrokerageModel.DefaultMarketMap[SecurityType.Future];
            }
            var canonicalSymbol   = Symbol.Create(leanSymbol, SecurityType.Future, market);
            var contractMonthYear = new DateTime(int.Parse(contractYearExpiration, CultureInfo.InvariantCulture), contractMonthExpiration, 1);
            // we get the expiration date using the FuturesExpiryFunctions
            var contractExpirationDate = FuturesExpiryFunctions.FuturesExpiryFunction(canonicalSymbol)(contractMonthYear);

            return(new Contract
            {
                Symbol = contractSymbol,
                Multiplier = malformedContract.Multiplier,
                LastTradeDateOrContractMonth = $"{contractExpirationDate:yyyyMMdd}",
                Exchange = malformedContract.Exchange,
                SecType = malformedContract.SecType,
                IncludeExpired = false,
                Currency = malformedContract.Currency
            });
        }
Exemplo n.º 2
0
        /// <summary>
        /// Parses a contract for options with malformed data.
        /// Malformed data usually manifests itself by having "0" assigned to some values
        /// we expect, like the contract's expiry date. The contract is returned by IB
        /// like this, usually due to a high amount of data subscriptions that are active
        /// in an account, surpassing IB's imposed limit. Read more about this here: https://interactivebrokers.github.io/tws-api/rtd_fqa_errors.html#rtd_common_errors_maxmktdata
        ///
        /// We are provided a string in the Symbol in malformed contracts that can be
        /// parsed to construct the clean contract, which is done by this method.
        /// </summary>
        /// <param name="malformedContract">Malformed contract (for options), i.e. a contract with invalid values ("0") in some of its fields</param>
        /// <param name="exchange">Exchange that the contract's asset lives on/where orders will be routed through</param>
        /// <returns>Clean Contract for the option</returns>
        /// <remarks>
        /// The malformed contract returns data similar to the following when calling <see cref="InteractiveBrokersBrokerage.GetContractDetails"/>:
        /// OPT SPY JUN2021 350 P [SPY 210618P00350000 100] USD 0 0 0
        ///
        /// ... which the contents inside [] follow the pattern:
        ///
        /// [SYMBOL YY_MM_DD_OPTIONRIGHT_STRIKE(divide by 1000) MULTIPLIER]
        /// </remarks>
        public static Contract ParseMalformedContractOptionSymbol(Contract malformedContract, string exchange = "Smart")
        {
            Log.Trace($"InteractiveBrokersSymbolMapper.ParseMalformedContractOptionSymbol(): Parsing malformed contract: {InteractiveBrokersBrokerage.GetContractDescription(malformedContract)} with trading class: \"{malformedContract.TradingClass}\"");

            // we search for the '[ ]' pattern, inside of it we: (capture any character except spaces, match spaces) -> 3 times
            var matches = Regex.Matches(malformedContract.Symbol, @"^.*[\[](\S*)\s*(\S*)\s*(\S*)[\]]");

            var match                 = matches[0].Groups;
            var contractSymbol        = match[1].Value;
            var contractSpecification = match[2].Value;
            var multiplier            = match[3].Value;
            var expiryDate            = "20" + contractSpecification.Substring(0, 6);
            var contractRight         = contractSpecification[6] == 'C' ? IB.RightType.Call : IB.RightType.Put;
            var contractStrike        = long.Parse(contractSpecification.Substring(7), CultureInfo.InvariantCulture) / 1000.0;

            return(new Contract
            {
                Symbol = contractSymbol,
                Multiplier = multiplier,
                LastTradeDateOrContractMonth = expiryDate,
                Right = contractRight,
                Strike = contractStrike,
                Exchange = exchange,
                SecType = malformedContract.SecType,
                IncludeExpired = false,
                Currency = malformedContract.Currency
            });
        }
Exemplo n.º 3
0
        /// <summary>
        /// Parses a contract for options with malformed data.
        /// Malformed data usually manifests itself by having "0" assigned to some values
        /// we expect, like the contract's expiry date. The contract is returned by IB
        /// like this, usually due to a high amount of data subscriptions that are active
        /// in an account, surpassing IB's imposed limit. Read more about this here: https://interactivebrokers.github.io/tws-api/rtd_fqa_errors.html#rtd_common_errors_maxmktdata
        ///
        /// We are provided a string in the Symbol in malformed contracts that can be
        /// parsed to construct the clean contract, which is done by this method.
        /// </summary>
        /// <param name="malformedContract">Malformed contract (for options), i.e. a contract with invalid values ("0") in some of its fields</param>
        /// <param name="exchange">Exchange that the contract's asset lives on/where orders will be routed through</param>
        /// <returns>Clean Contract for the option</returns>
        /// <remarks>
        /// The malformed contract returns data similar to the following when calling <see cref="InteractiveBrokersBrokerage.GetContractDetails"/>:
        /// OPT SPY JUN2021 350 P [SPY 210618P00350000 100] USD 0 0 0
        ///
        /// ... which the contents inside [] follow the pattern:
        ///
        /// [SYMBOL YY_MM_DD_OPTIONRIGHT_STRIKE(divide by 1000) MULTIPLIER]
        /// </remarks>
        public static Contract ParseMalformedContractOptionSymbol(Contract malformedContract, string exchange = "Smart")
        {
            Log.Trace($"InteractiveBrokersSymbolMapper.ParseMalformedContractOptionSymbol(): Parsing malformed contract: {InteractiveBrokersBrokerage.GetContractDescription(malformedContract)} with trading class: \"{malformedContract.TradingClass}\"");

            var contractInfoSplit = malformedContract.Symbol.Substring(malformedContract.Symbol.IndexOf('['))
                                    .Replace("[", "")
                                    .Replace("]", "")
                                    .Split(' ');

            var contractSymbol        = contractInfoSplit[0];
            var contractSpecification = contractInfoSplit[1];
            var multiplier            = contractInfoSplit[2];
            var expiryDate            = "20" + contractSpecification.Substring(0, 6);
            var contractRight         = contractSpecification[6] == 'C' ? IB.RightType.Call : IB.RightType.Put;
            var contractStrike        = long.Parse(contractSpecification.Substring(7), CultureInfo.InvariantCulture) / 1000.0;

            return(new Contract
            {
                Symbol = contractSymbol,
                Multiplier = multiplier,
                LastTradeDateOrContractMonth = expiryDate,
                Right = contractRight,
                Strike = contractStrike,
                Exchange = exchange,
                SecType = malformedContract.SecType,
                IncludeExpired = false,
                Currency = malformedContract.Currency
            });
        }