コード例 #1
0
        /// <summary>
        /// The check daily volume breach.
        /// </summary>
        /// <param name="opposingPosition">
        /// The opposing position.
        /// </param>
        /// <param name="mostRecentTrade">
        /// The most recent trade.
        /// </param>
        /// <returns>
        /// The <see cref="RuleBreachDescription"/>.
        /// </returns>
        private RuleBreachDescription CheckDailyVolumeBreach(
            ITradePosition opposingPosition,
            Order mostRecentTrade)
        {
            var tradingHoursManager = this.tradingHoursService.GetTradingHoursForMic(mostRecentTrade.Market.MarketIdentifierCode);

            if (!tradingHoursManager.IsValid)
            {
                this.logger.LogInformation($"unable to fetch market data for ({mostRecentTrade.Market.MarketIdentifierCode}) for the most recent trade {mostRecentTrade?.Instrument?.Identifiers} the market data did not contain the security indicated as trading in that market");

                this.hadMissingData = true;
                return(RuleBreachDescription.False());
            }

            var marketRequest =
                new MarketDataRequest(
                    mostRecentTrade.Market.MarketIdentifierCode,
                    mostRecentTrade.Instrument.Cfi,
                    mostRecentTrade.Instrument.Identifiers,
                    tradingHoursManager.OpeningInUtcForDay(UniverseDateTime.Subtract(this.TradeBackwardWindowSize)),
                    tradingHoursManager.ClosingInUtcForDay(UniverseDateTime),
                    this.ruleContext?.Id(),
                    DataSource.AnyInterday);

            var marketResult = UniverseEquityInterdayCache.Get(marketRequest);

            if (marketResult.HadMissingData)
            {
                this.logger.LogInformation($"unable to fetch market data for ({mostRecentTrade.Market.MarketIdentifierCode}) for the most recent trade {mostRecentTrade?.Instrument?.Identifiers} the market data did not contain the security indicated as trading in that market");

                this.hadMissingData = true;
                return(RuleBreachDescription.False());
            }

            var marketSecurityData = marketResult.Response;

            if (marketSecurityData?.DailySummaryTimeBar?.DailyVolume.Traded <= 0 ||
                opposingPosition.TotalVolumeOrderedOrFilled() <= 0)
            {
                this.logger.LogInformation($"unable to evaluate for {mostRecentTrade?.Instrument?.Identifiers} either the market daily volume data was not available or the opposing position had a bad total volume value (daily volume){marketSecurityData?.DailySummaryTimeBar?.DailyVolume.Traded} - (opposing position){opposingPosition.TotalVolumeOrderedOrFilled()}");

                this.hadMissingData = true;
                return(RuleBreachDescription.False());
            }

            var percentageDailyVolume = (decimal)opposingPosition.TotalVolumeOrderedOrFilled() / (decimal)marketSecurityData?.DailySummaryTimeBar?.DailyVolume.Traded;

            if (percentageDailyVolume >= this.equitiesParameters.PercentageOfMarketDailyVolume)
            {
                return(new RuleBreachDescription
                {
                    RuleBreached = true,
                    Description = $" Percentage of market daily volume traded within a {this.equitiesParameters.Windows.BackwardWindowSize.TotalSeconds} second window exceeded the layering window threshold of {this.equitiesParameters.PercentageOfMarketDailyVolume * 100}%."
                });
            }

            return(RuleBreachDescription.False());
        }
コード例 #2
0
        /// <summary>
        /// The daily volume check.
        /// </summary>
        /// <param name="mostRecentTrade">
        /// The most recent trade.
        /// </param>
        /// <param name="tradedVolume">
        /// The traded volume.
        /// </param>
        /// <returns>
        /// The <see cref="BreachDetails"/>.
        /// </returns>
        private HighVolumeRuleBreach.BreachDetails DailyVolumeCheck(Order mostRecentTrade, decimal tradedVolume)
        {
            if (mostRecentTrade == null)
            {
                return(HighVolumeRuleBreach.BreachDetails.None());
            }

            var tradingHours = this.TradingHoursService.GetTradingHoursForMic(mostRecentTrade.Market?.MarketIdentifierCode);

            if (!tradingHours.IsValid)
            {
                this.Logger.LogError($"Request for trading hours was invalid. MIC - {mostRecentTrade.Market?.MarketIdentifierCode}");
            }

            var marketDataRequest = new MarketDataRequest(
                mostRecentTrade.Market?.MarketIdentifierCode,
                mostRecentTrade.Instrument.Cfi,
                mostRecentTrade.Instrument.Identifiers,
                tradingHours.OpeningInUtcForDay(UniverseDateTime.Subtract(this.TradeBackwardWindowSize)),
                tradingHours.ClosingInUtcForDay(UniverseDateTime),
                this.RuleCtx?.Id(),
                DataSource.AnyInterday);

            var securityResult = UniverseEquityInterdayCache.Get(marketDataRequest);

            if (securityResult.HadMissingData)
            {
                this.HadMissingData = true;
                this.Logger.LogWarning($"Missing data for {marketDataRequest}.");
                return(HighVolumeRuleBreach.BreachDetails.None());
            }

            var security  = securityResult.Response;
            var threshold = (long)Math.Ceiling(
                this.EquitiesParameters.HighVolumePercentageDaily.GetValueOrDefault(0) * security.DailySummaryTimeBar.DailyVolume.Traded);

            if (threshold <= 0)
            {
                this.HadMissingData = true;
                this.Logger.LogInformation($"Daily volume threshold of {threshold} was recorded.");
                return(HighVolumeRuleBreach.BreachDetails.None());
            }

            var breachPercentage =
                security.DailySummaryTimeBar.DailyVolume.Traded != 0 && tradedVolume != 0
                    ? (decimal)tradedVolume / (decimal)security.DailySummaryTimeBar.DailyVolume.Traded
                    : 0;

            if (tradedVolume >= threshold)
            {
                return(new HighVolumeRuleBreach.BreachDetails(true, breachPercentage, threshold, mostRecentTrade.Market));
            }

            return(HighVolumeRuleBreach.BreachDetails.None());
        }
コード例 #3
0
        /// <summary>
        /// The check daily volume traded.
        /// </summary>
        /// <param name="securities">
        /// The securities.
        /// </param>
        /// <returns>
        /// The <see cref="VolumeBreach"/>.
        /// </returns>
        private VolumeBreach CheckDailyVolumeTraded(
            Stack <Order> securities)
        {
            if (!securities.Any())
            {
                return(new VolumeBreach());
            }

            var marketDataRequest = new MarketDataRequest(
                securities.Peek().Market.MarketIdentifierCode,
                securities.Peek().Instrument.Cfi,
                securities.Peek().Instrument.Identifiers,
                UniverseDateTime.Subtract(this.TradeBackwardWindowSize), // implicitly correct (market closure event trigger)
                UniverseDateTime,
                this.ruleContext?.Id(),
                DataSource.AnyInterday);

            var dataResponse = UniverseEquityInterdayCache.Get(marketDataRequest);

            if (dataResponse.HadMissingData)
            {
                this.hadMissingData = true;
                this.logger.LogInformation($"had missing data for {securities.Peek().Instrument.Identifiers} on {UniverseDateTime}");
                return(new VolumeBreach());
            }

            var tradedSecurity = dataResponse.Response;

            var thresholdVolumeTraded = tradedSecurity.DailySummaryTimeBar.DailyVolume.Traded * this.equitiesParameters.PercentageThresholdDailyVolume;

            if (thresholdVolumeTraded == null)
            {
                this.hadMissingData = true;
                return(new VolumeBreach());
            }

            var result =
                this.CalculateVolumeBreaches(
                    securities,
                    thresholdVolumeTraded.GetValueOrDefault(0),
                    tradedSecurity.DailySummaryTimeBar.DailyVolume.Traded);

            return(result);
        }