コード例 #1
0
        public SpoofingRuleBreach(
            IFactorValue factorValue,
            ISystemProcessOperationContext operationContext,
            string correlationId,
            TimeSpan window,
            ITradePosition fulfilledTradePosition,
            ITradePosition cancelledTradePosition,
            FinancialInstrument security,
            Order mostRecentTrade,
            ISpoofingRuleEquitiesParameters spoofingEquitiesParameters,
            string description,
            string caseTitle,
            DateTime universeDateTime)
        {
            this.FactorValue = factorValue;

            this.Window          = window;
            this.Security        = security;
            this.MostRecentTrade = mostRecentTrade;

            var totalTrades = fulfilledTradePosition.Get().ToList();

            totalTrades.AddRange(cancelledTradePosition.Get());
            this.Trades = new TradePosition(totalTrades);
            this.TradesInFulfilledPosition = fulfilledTradePosition;
            this.CancelledTrades           = cancelledTradePosition;

            this.RuleParameterId   = spoofingEquitiesParameters?.Id ?? string.Empty;
            this.SystemOperationId = operationContext.Id.ToString();
            this.CorrelationId     = correlationId;
            this.RuleParameters    = spoofingEquitiesParameters;
            this.Description       = description ?? string.Empty;
            this.CaseTitle         = caseTitle ?? string.Empty;
            this.UniverseDateTime  = universeDateTime;
        }
コード例 #2
0
 public LayeringRuleBreach(
     IFactorValue factorValue,
     ISystemProcessOperationContext operationContext,
     string correlationId,
     ILayeringRuleEquitiesParameters equitiesParameters,
     TimeSpan window,
     ITradePosition trades,
     FinancialInstrument security,
     RuleBreachDescription bidirectionalTradeBreach,
     RuleBreachDescription dailyVolumeTradeBreach,
     RuleBreachDescription windowVolumeTradeBreach,
     RuleBreachDescription priceMovementBreach,
     string description,
     string caseTitle,
     DateTime universeDateTime)
 {
     this.FactorValue              = factorValue;
     this.EquitiesParameters       = equitiesParameters;
     this.Window                   = window;
     this.Trades                   = trades;
     this.Security                 = security;
     this.BidirectionalTradeBreach = bidirectionalTradeBreach;
     this.DailyVolumeTradeBreach   = dailyVolumeTradeBreach;
     this.WindowVolumeTradeBreach  = windowVolumeTradeBreach;
     this.PriceMovementBreach      = priceMovementBreach;
     this.RuleParameterId          = equitiesParameters?.Id ?? string.Empty;
     this.SystemOperationId        = operationContext.Id.ToString();
     this.CorrelationId            = correlationId;
     this.RuleParameters           = equitiesParameters;
     this.Description              = description ?? string.Empty;
     this.CaseTitle                = caseTitle ?? string.Empty;
     this.UniverseDateTime         = universeDateTime;
 }
コード例 #3
0
        public PlacingOrderWithNoIntentToExecuteRuleRuleBreach(
            TimeSpan window,
            ITradePosition trades,
            FinancialInstrument security,
            IFactorValue factorValue,
            decimal meanPrice,
            decimal sdPrice,
            IReadOnlyCollection <ProbabilityOfExecution> probabilityForOrders,
            IPlacingOrderWithNoIntentToExecuteRuleEquitiesParameters parameters,
            ISystemProcessOperationRunRuleContext ctx,
            string description,
            string caseTitle,
            DateTime universeDateTime)
        {
            this.Window   = window;
            this.Trades   = trades;
            this.Security = security;

            this.FactorValue = factorValue;
            this.Parameters  = parameters;

            this.MeanPrice = meanPrice;
            this.StandardDeviationPrice = sdPrice;
            this.ProbabilityForOrders   = probabilityForOrders ?? new List <ProbabilityOfExecution>();

            this.RuleParameterId   = parameters.Id;
            this.SystemOperationId = ctx.Id();
            this.CorrelationId     = ctx.CorrelationId();
            this.RuleParameters    = parameters;
            this.Description       = description ?? string.Empty;
            this.CaseTitle         = caseTitle ?? string.Empty;
            this.UniverseDateTime  = universeDateTime;
        }
コード例 #4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RuleBreach"/> class.
 /// </summary>
 /// <param name="window">
 /// The window.
 /// </param>
 /// <param name="trades">
 /// The trades.
 /// </param>
 /// <param name="security">
 /// The security.
 /// </param>
 /// <param name="isBackTestRun">
 /// The is back test run.
 /// </param>
 /// <param name="ruleParameterId">
 /// The rule parameter id.
 /// </param>
 /// <param name="systemOperationId">
 /// The system operation id.
 /// </param>
 /// <param name="correlationId">
 /// The correlation id.
 /// </param>
 /// <param name="factorValue">
 /// The factor value.
 /// </param>
 /// <param name="ruleParameter">
 /// The rule parameter.
 /// </param>
 /// <param name="universeDateTime">
 /// The universe date time.
 /// </param>
 /// <param name="description">
 /// The description.
 /// </param>
 /// <param name="caseTitle">
 /// The case title.
 /// </param>
 public RuleBreach(
     TimeSpan window,
     ITradePosition trades,
     FinancialInstrument security,
     bool isBackTestRun,
     string ruleParameterId,
     string systemOperationId,
     string correlationId,
     IFactorValue factorValue,
     IRuleParameter ruleParameter,
     DateTime universeDateTime,
     string description,
     string caseTitle)
 {
     this.Window            = window;
     this.Trades            = trades;
     this.Security          = security;
     this.IsBackTestRun     = isBackTestRun;
     this.RuleParameterId   = ruleParameterId;
     this.SystemOperationId = systemOperationId;
     this.CorrelationId     = correlationId;
     this.FactorValue       = factorValue;
     this.RuleParameters    = ruleParameter;
     this.UniverseDateTime  = universeDateTime;
     this.Description       = description;
     this.CaseTitle         = caseTitle;
 }
コード例 #5
0
 public RampingRuleBreach(
     TimeSpan window,
     ITradePosition trades,
     FinancialInstrument security,
     string ruleParameterId,
     string systemOperationId,
     string correlationId,
     IFactorValue factorValue,
     IRampingStrategySummaryPanel summaryPanel,
     IRampingRuleEquitiesParameters parameters,
     string description,
     string caseTitle,
     DateTime universeDateTime)
 {
     this.Window            = window;
     this.Trades            = trades;
     this.Security          = security;
     this.RuleParameterId   = ruleParameterId ?? string.Empty;
     this.SystemOperationId = systemOperationId ?? string.Empty;
     this.CorrelationId     = correlationId ?? string.Empty;
     this.FactorValue       = factorValue;
     this.SummaryPanel      = summaryPanel;
     this.RuleParameters    = parameters;
     this.Description       = description ?? string.Empty;
     this.CaseTitle         = caseTitle ?? string.Empty;
     this.UniverseDateTime  = universeDateTime;
 }
コード例 #6
0
        public MarkingTheCloseBreach(
            IFactorValue factorValue,
            ISystemProcessOperationContext operationContext,
            string correlationId,
            TimeSpan window,
            FinancialInstrument security,
            MarketOpenClose marketClose,
            ITradePosition tradingPosition,
            IMarkingTheCloseEquitiesParameters equitiesParameters,
            VolumeBreach dailyBreach,
            VolumeBreach windowBreach,
            string description,
            string caseTitle,
            DateTime universeDateTime)
        {
            this.FactorValue = factorValue;

            this.Window   = window;
            this.Security = security ?? throw new ArgumentNullException(nameof(security));

            this.MarketClose        = marketClose ?? throw new ArgumentNullException(nameof(marketClose));
            this.Trades             = tradingPosition ?? new TradePosition(new List <Order>());
            this.EquitiesParameters = equitiesParameters ?? throw new ArgumentNullException(nameof(equitiesParameters));

            this.DailyBreach  = dailyBreach;
            this.WindowBreach = windowBreach;

            this.RuleParameterId   = equitiesParameters?.Id ?? string.Empty;
            this.SystemOperationId = operationContext.Id.ToString();
            this.CorrelationId     = correlationId;
            this.RuleParameters    = equitiesParameters;
            this.Description       = description ?? string.Empty;
            this.CaseTitle         = caseTitle ?? string.Empty;
            this.UniverseDateTime  = universeDateTime;
        }
コード例 #7
0
        public WashTradeRuleBreach(
            TimeSpan windowSize,
            IFactorValue factorValue,
            ISystemProcessOperationContext operationContext,
            string correlationId,
            IWashTradeRuleParameters equitiesParameters,
            ITradePosition tradePosition,
            FinancialInstrument security,
            WashTradeAveragePositionBreach averagePositionBreach,
            WashTradeClusteringPositionBreach clusteringPositionBreach,
            string description,
            string caseTitle,
            DateTime universeDateTime)
        {
            this.FactorValue        = factorValue;
            this.EquitiesParameters = equitiesParameters ?? throw new ArgumentNullException(nameof(equitiesParameters));

            this.Window   = windowSize;
            this.Trades   = tradePosition;
            this.Security = security;

            this.AveragePositionBreach =
                averagePositionBreach ?? throw new ArgumentNullException(nameof(averagePositionBreach));
            this.ClusteringPositionBreach = clusteringPositionBreach
                                            ?? throw new ArgumentNullException(nameof(clusteringPositionBreach));

            this.RuleParameterId   = equitiesParameters?.Id ?? string.Empty;
            this.SystemOperationId = operationContext.Id.ToString();
            this.CorrelationId     = correlationId;
            this.RuleParameters    = equitiesParameters;
            this.Description       = description ?? string.Empty;
            this.CaseTitle         = caseTitle ?? string.Empty;
            this.UniverseDateTime  = universeDateTime;
        }
コード例 #8
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());
        }
コード例 #9
0
        /// <summary>
        ///     Check if the current position (this) is a subset of the provided (arg) position
        ///     uses BY REFERENCE for comparision
        /// </summary>
        public bool PositionIsSubsetOf(ITradePosition position)
        {
            if (position == null)
            {
                return(false);
            }

            return(!this._trades.Except(position.Get()).Any());
        }
コード例 #10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="FixedIncomeHighVolumeJudgementContext"/> class.
 /// </summary>
 /// <param name="judgement">
 /// The judgement.
 /// </param>
 /// <param name="raiseRuleViolation">
 /// The project to alert.
 /// </param>
 /// <param name="tradePosition">
 /// The trade position.
 /// </param>
 /// <param name="venue">
 /// The venue.
 /// </param>
 public FixedIncomeHighVolumeJudgementContext(
     IFixedIncomeHighVolumeJudgement judgement,
     bool raiseRuleViolation,
     ITradePosition tradePosition,
     Market venue)
 {
     this.Judgement          = judgement ?? throw new ArgumentNullException(nameof(judgement));
     this.RaiseRuleViolation = raiseRuleViolation;
     this.TradePosition      = tradePosition ?? throw new ArgumentNullException(nameof(tradePosition));
     this.Venue = venue;
 }
コード例 #11
0
        /// <summary>
        /// Check if the current position (this) is a subset of the provided (argument) position uses BY REFERENCE for comparison
        /// </summary>
        /// <param name="position">
        /// The position.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public bool PositionIsSubsetOf(ITradePosition position)
        {
            if (position == null)
            {
                return(false);
            }

            if (position.Get().SequenceEqual(this.trades))
            {
                return(true);
            }

            return(!this.trades.Except(position.Get()).Any());
        }
コード例 #12
0
 public ExchangeRateProfitBreakdown(
     ITradePosition positionCost,
     ITradePosition positionRevenue,
     decimal positionCostWer,
     decimal positionRevenueWer,
     Domain.Core.Financial.Money.Currency fixedCurrency,
     Domain.Core.Financial.Money.Currency variableCurrency)
 {
     this.PositionCost       = positionCost;
     this.PositionRevenue    = positionRevenue;
     this.PositionCostWer    = positionCostWer;
     this.PositionRevenueWer = positionRevenueWer;
     this.FixedCurrency      = fixedCurrency;
     this.VariableCurrency   = variableCurrency;
 }
コード例 #13
0
        public async Task <decimal> WeightedExchangeRate(
            ITradePosition position,
            Currency targetCurrency,
            ISystemProcessOperationRunRuleContext ruleCtx)
        {
            if (position == null || position.TotalVolume() == 0)
            {
                this._logger.LogInformation(
                    "asked to calculate WER for either null position or position with 0 volume. Returning 0");
                return(0);
            }

            var totalVolume   = position.TotalVolume();
            var weightedRates = new List <WeightedXRate>();

            foreach (var order in position.Get())
            {
                if (order.OrderFilledVolume.GetValueOrDefault() == 0)
                {
                    continue;
                }

                var weight = order.OrderFilledVolume.GetValueOrDefault(0) / totalVolume;

                var rate = await this._exchangeRatesService.GetRate(
                    order.OrderCurrency,
                    targetCurrency,
                    order.MostRecentDateEvent(),
                    ruleCtx);

                weightedRates.Add(new WeightedXRate(weight, (decimal?)rate?.Rate ?? 0m));
            }

            foreach (var item in weightedRates)
            {
                if (item == null)
                {
                    continue;
                }

                this._logger.LogInformation($"had a sub component with {item.Weight} and {item.XRate}");
            }

            var weightedAverage = weightedRates.Sum(wr => wr.Weight * wr.XRate);

            return(weightedAverage);
        }
        public async Task <ExchangeRateProfitBreakdown> ExchangeRateMovement(
            ITradePosition positionCost,
            ITradePosition positionRevenue,
            Domain.Core.Financial.Money.Currency variableCurrency,
            ISystemProcessOperationRunRuleContext ruleCtx)
        {
            if (string.IsNullOrEmpty(variableCurrency.Code))
            {
                this._logger.LogInformation(
                    "ExchangeRateProfitCalculator ExchangeRateMovement had a null or empty variable currency. Returning null.");
                return(null);
            }

            var orderCurrency = positionCost.Get()
                                .FirstOrDefault(pos => !string.IsNullOrWhiteSpace(pos.OrderCurrency.Code))?.OrderCurrency;

            if (string.Equals(orderCurrency?.Code, variableCurrency.Code, StringComparison.InvariantCultureIgnoreCase))
            {
                this._logger.LogInformation(
                    "ExchangeRateProfitCalculator ExchangeRateMovement could not find an order currency. Returning null.");
                return(null);
            }

            if (string.IsNullOrWhiteSpace(orderCurrency.GetValueOrDefault().Code))
            {
                orderCurrency = positionRevenue.Get()
                                .FirstOrDefault(pos => !string.IsNullOrWhiteSpace(pos.OrderCurrency.Code))?.OrderCurrency;
            }

            var costRates =
                await this._werExchangeRateService.WeightedExchangeRate(positionCost, variableCurrency, ruleCtx);

            var revenueRates = await this._werExchangeRateService.WeightedExchangeRate(
                positionRevenue,
                variableCurrency,
                ruleCtx);

            var breakdown = new ExchangeRateProfitBreakdown(
                positionCost,
                positionRevenue,
                costRates,
                revenueRates,
                orderCurrency.GetValueOrDefault(),
                variableCurrency);

            return(breakdown);
        }
コード例 #15
0
        /// <summary>
        /// The add to positions.
        /// </summary>
        /// <param name="buyPosition">
        /// The buy position.
        /// </param>
        /// <param name="sellPosition">
        /// The sell position.
        /// </param>
        /// <param name="nextTrade">
        /// The next trade.
        /// </param>
        private void AddToPositions(ITradePosition buyPosition, ITradePosition sellPosition, Order nextTrade)
        {
            switch (nextTrade.OrderDirection)
            {
            case OrderDirections.BUY:
            case OrderDirections.COVER:
                buyPosition.Add(nextTrade);
                break;

            case OrderDirections.SELL:
            case OrderDirections.SHORT:
                sellPosition.Add(nextTrade);
                break;

            default:
                this.logger.LogError("not considering an out of range order direction");
                this.ruleContext.EventException("not considering an out of range order direction");
                throw new ArgumentOutOfRangeException(nameof(nextTrade));
            }
        }
コード例 #16
0
        public HighVolumeRuleBreach(
            IFactorValue factorValue,
            ISystemProcessOperationContext operationContext,
            string correlationId,
            TimeSpan window,
            ITradePosition trades,
            FinancialInstrument security,
            IHighVolumeRuleEquitiesParameters equitiesParameters,
            BreachDetails dailyBreach,
            BreachDetails windowBreach,
            BreachDetails marketCapBreach,
            decimal totalOrdersTradedInWindow,
            string description,
            string caseTitle,
            DateTime universeDateTime)
        {
            this.FactorValue = factorValue;

            this.Window             = window;
            this.Trades             = trades;
            this.Security           = security;
            this.EquitiesParameters = equitiesParameters;

            this.DailyBreach     = dailyBreach;
            this.WindowBreach    = windowBreach;
            this.MarketCapBreach = marketCapBreach;

            this.TotalOrdersTradedInWindow = totalOrdersTradedInWindow;
            this.RuleParameterId           = equitiesParameters?.Id ?? string.Empty;
            this.SystemOperationId         = operationContext.Id.ToString();
            this.CorrelationId             = correlationId;
            this.RuleParameters            = equitiesParameters;
            this.Description      = description ?? string.Empty;
            this.CaseTitle        = caseTitle ?? string.Empty;
            this.UniverseDateTime = universeDateTime;
        }
コード例 #17
0
 public CancelledOrderRuleBreach(
     IFactorValue factorValue,
     ISystemProcessOperationContext ctx,
     string correlationId,
     ICancelledOrderRuleEquitiesParameters parameters,
     ITradePosition trades,
     FinancialInstrument security,
     bool exceededPercentagePositionCancellations,
     decimal?percentagePositionCancelled,
     int?amountOfPositionCancelled,
     int?amountOfPositionInTotal,
     bool exceededPercentageTradeCountCancellations,
     decimal?percentageTradeCountCancelled,
     string description,
     string caseTitle,
     DateTime universeDateTime)
 {
     this.FactorValue = factorValue;
     this.Parameters  = parameters;
     this.Trades      = trades;
     this.Security    = security;
     this.ExceededPercentagePositionCancellations = exceededPercentagePositionCancellations;
     this.PercentagePositionCancelled             = percentagePositionCancelled;
     this.AmountOfPositionCancelled = amountOfPositionCancelled;
     this.AmountOfPositionInTotal   = amountOfPositionInTotal;
     this.ExceededPercentageTradeCountCancellations = exceededPercentageTradeCountCancellations;
     this.PercentageTradeCountCancelled             = percentageTradeCountCancelled;
     this.Window            = parameters.Windows.BackwardWindowSize;
     this.RuleParameterId   = this.Parameters?.Id ?? string.Empty;
     this.SystemOperationId = ctx.Id.ToString();
     this.CorrelationId     = correlationId;
     this.RuleParameters    = this.Parameters;
     this.Description       = description ?? string.Empty;
     this.CaseTitle         = caseTitle ?? string.Empty;
     this.UniverseDateTime  = universeDateTime;
 }
 public void Setup()
 {
     this.tradePosition = A.Fake <ITradePosition>();
     this.judgement     = A.Fake <IFixedIncomeHighVolumeJudgement>();
     this.market        = new Market("id-1", "XLON", "London Stock Exchange", MarketTypes.STOCKEXCHANGE);
 }
コード例 #19
0
        /// <summary>
        /// The check for price movement.
        /// </summary>
        /// <param name="opposingPosition">
        /// The opposing position.
        /// </param>
        /// <param name="mostRecentTrade">
        /// The most recent trade.
        /// </param>
        /// <returns>
        /// The <see cref="RuleBreachDescription"/>.
        /// </returns>
        private RuleBreachDescription CheckForPriceMovement(
            ITradePosition opposingPosition,
            Order mostRecentTrade)
        {
            var startDate = opposingPosition.Get().Where(op => op.PlacedDate != null).Min(op => op.PlacedDate).GetValueOrDefault();
            var endDate   = opposingPosition.Get().Where(op => op.PlacedDate != null).Max(op => op.PlacedDate).GetValueOrDefault();

            if (endDate.Subtract(startDate) < TimeSpan.FromMinutes(1))
            {
                endDate = endDate.AddMinutes(1);
            }

            var marketRequest =
                new MarketDataRequest(
                    mostRecentTrade.Market.MarketIdentifierCode,
                    mostRecentTrade.Instrument.Cfi,
                    mostRecentTrade.Instrument.Identifiers,
                    startDate.Subtract(this.TradeBackwardWindowSize),
                    endDate,
                    this.ruleContext?.Id(),
                    DataSource.AnyIntraday);

            var tradingDays =
                this.tradingHoursService.GetTradingDaysWithinRangeAdjustedToTime(
                    UniverseDateTime.Subtract(this.TradeBackwardWindowSize),
                    UniverseDateTime,
                    mostRecentTrade.Market.MarketIdentifierCode);

            var marketResult = UniverseEquityIntradayCache.GetMarketsForRange(marketRequest, tradingDays, RunMode);

            if (marketResult.HadMissingData)
            {
                this.logger.LogInformation($"unable to fetch market data frames for {mostRecentTrade.Market.MarketIdentifierCode} at {UniverseDateTime}.");

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

            if (mostRecentTrade.PlacedDate > endDate)
            {
                endDate = mostRecentTrade.PlacedDate.GetValueOrDefault();
            }

            var securityDataTicks = marketResult.Response;
            var startTick         = this.StartTick(securityDataTicks, startDate);

            if (startTick == null)
            {
                this.logger.LogInformation($"unable to fetch starting exchange tick data for ({startDate}) {mostRecentTrade.Market.MarketIdentifierCode} at {UniverseDateTime}.");

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

            var endTick = this.EndTick(securityDataTicks, endDate);

            if (endTick == null)
            {
                this.logger.LogInformation($"unable to fetch ending exchange tick data for ({endDate}) {mostRecentTrade.Market.MarketIdentifierCode} at {UniverseDateTime}.");

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

            var priceMovement = endTick.SpreadTimeBar.Price.Value - startTick.SpreadTimeBar.Price.Value;

            return(this.BuildDescription(mostRecentTrade, priceMovement, startTick, endTick));
        }
コード例 #20
0
        /// <summary>
        /// The check window 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 CheckWindowVolumeBreach(
            ITradePosition opposingPosition,
            Order mostRecentTrade)
        {
            var marketDataRequest =
                new MarketDataRequest(
                    mostRecentTrade.Market.MarketIdentifierCode,
                    mostRecentTrade.Instrument.Cfi,
                    mostRecentTrade.Instrument.Identifiers,
                    UniverseDateTime.Subtract(this.TradeBackwardWindowSize),
                    UniverseDateTime,
                    this.ruleContext?.Id(),
                    DataSource.AnyIntraday);

            var tradingDays =
                this.tradingHoursService.GetTradingDaysWithinRangeAdjustedToTime(
                    UniverseDateTime.Subtract(this.TradeBackwardWindowSize),
                    UniverseDateTime,
                    mostRecentTrade.Market.MarketIdentifierCode);

            var securityResult = UniverseEquityIntradayCache.GetMarketsForRange(marketDataRequest, tradingDays, RunMode);

            if (securityResult.HadMissingData)
            {
                this.logger.LogWarning($"unable to fetch market data frames for {mostRecentTrade.Market.MarketIdentifierCode} at {UniverseDateTime}.");

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

            var windowVolume = securityResult.Response.Sum(sdt => sdt?.SpreadTimeBar.Volume.Traded);

            if (windowVolume <= 0)
            {
                this.logger.LogInformation($"unable to sum meaningful volume from market data frames for volume window in {mostRecentTrade.Market.MarketIdentifierCode} at {UniverseDateTime}.");

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

            if (opposingPosition.TotalVolumeOrderedOrFilled() <= 0)
            {
                this.logger.LogInformation($"unable to calculate opposing position volume window in {mostRecentTrade.Market.MarketIdentifierCode} at {UniverseDateTime}.");

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

            var percentageWindowVolume = (decimal)opposingPosition.TotalVolumeOrderedOrFilled() / (decimal)windowVolume;

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

            return(RuleBreachDescription.False());
        }
コード例 #21
0
        /// <summary>
        /// The check position for layering.
        /// </summary>
        /// <param name="tradeWindow">
        /// The trade window.
        /// </param>
        /// <param name="buyPosition">
        /// The buy position.
        /// </param>
        /// <param name="sellPosition">
        /// The sell position.
        /// </param>
        /// <param name="tradingPosition">
        /// The trading position.
        /// </param>
        /// <param name="opposingPosition">
        /// The opposing position.
        /// </param>
        /// <param name="mostRecentTrade">
        /// The most recent trade.
        /// </param>
        /// <returns>
        /// The <see cref="ILayeringRuleBreach"/>.
        /// </returns>
        private ILayeringRuleBreach CheckPositionForLayering(
            Stack <Order> tradeWindow,
            ITradePosition buyPosition,
            ITradePosition sellPosition,
            ITradePosition tradingPosition,
            ITradePosition opposingPosition,
            Order mostRecentTrade)
        {
            var hasTradesInWindow = tradeWindow.Any();
            RuleBreachDescription hasBidirectionalBreach = RuleBreachDescription.False();
            RuleBreachDescription hasDailyVolumeBreach   = RuleBreachDescription.False();
            RuleBreachDescription hasWindowVolumeBreach  = RuleBreachDescription.False();
            RuleBreachDescription priceMovementBreach    = RuleBreachDescription.False();

            // ReSharper disable once LoopVariableIsNeverChangedInsideLoop
            while (hasTradesInWindow)
            {
                if (!tradeWindow.Any())
                {
                    // ReSharper disable once RedundantAssignment
                    hasTradesInWindow = false;
                    break;
                }

                var nextTrade = tradeWindow.Pop();
                this.AddToPositions(buyPosition, sellPosition, nextTrade);

                if (!tradingPosition.Get().Any() ||
                    !opposingPosition.Get().Any())
                {
                    continue;
                }

                // IF ALL PARAMETERS ARE NULL JUST DO THE BIDIRECTIONAL TRADE CHECK
                if (this.equitiesParameters.PercentageOfMarketDailyVolume == null &&
                    this.equitiesParameters.PercentageOfMarketWindowVolume == null &&
                    this.equitiesParameters.CheckForCorrespondingPriceMovement == null)
                {
                    hasBidirectionalBreach = new RuleBreachDescription
                    {
                        RuleBreached = true,
                        Description  = " Trading in both buy/sell positions simultaneously was detected."
                    };
                }

                if (this.equitiesParameters.PercentageOfMarketDailyVolume != null)
                {
                    hasDailyVolumeBreach = this.CheckDailyVolumeBreach(opposingPosition, mostRecentTrade);
                }

                if (this.equitiesParameters.PercentageOfMarketWindowVolume != null)
                {
                    hasWindowVolumeBreach = this.CheckWindowVolumeBreach(opposingPosition, mostRecentTrade);
                }

                if (this.equitiesParameters.CheckForCorrespondingPriceMovement != null &&
                    this.equitiesParameters.CheckForCorrespondingPriceMovement.Value)
                {
                    priceMovementBreach = this.CheckForPriceMovement(opposingPosition, mostRecentTrade);
                }
            }

            var allTradesInPositions = opposingPosition.Get().Concat(tradingPosition.Get()).ToList();
            var allTrades            = new TradePosition(allTradesInPositions);

            if (!this.HasRuleBreach(
                    hasBidirectionalBreach,
                    hasDailyVolumeBreach,
                    hasWindowVolumeBreach,
                    priceMovementBreach))
            {
                return(null);
            }

            return(new LayeringRuleBreach(
                       this.OrganisationFactorValue,
                       this.ruleContext.SystemProcessOperationContext(),
                       this.ruleContext.CorrelationId(),
                       this.equitiesParameters,
                       this.equitiesParameters.Windows?.BackwardWindowSize ?? TimeSpan.Zero,
                       allTrades,
                       mostRecentTrade.Instrument,
                       hasBidirectionalBreach,
                       hasDailyVolumeBreach,
                       hasWindowVolumeBreach,
                       priceMovementBreach,
                       null,
                       null,
                       UniverseDateTime));
        }