예제 #1
0
 public void Setup()
 {
     this.fixedIncomeHighProfitJudgement = A.Fake <IFixedIncomeHighProfitJudgement>();
     this.ruleBreachContext     = A.Fake <IRuleBreachContext>();
     this.fixedIncomeParameters = A.Fake <IHighProfitsRuleFixedIncomeParameters>();
     this.profitBreakdown       = A.Fake <IExchangeRateProfitBreakdown>();
 }
 public void Setup()
 {
     this.logger            = A.Fake <ILogger <FixedIncomeHighProfitJudgementMapper> >();
     this.judgementContext  = A.Fake <IFixedIncomeHighProfitJudgementContext>();
     this.ruleBreachContext = A.Fake <IRuleBreachContext>();
     this.parameters        = A.Fake <IHighProfitsRuleFixedIncomeParameters>();
     this.profitBreakdown   = A.Fake <IExchangeRateProfitBreakdown>();
 }
예제 #3
0
        /// <summary>
        /// The set judgement for full analysis covers downstream logic for its code branch.
        /// </summary>
        /// <param name="absoluteProfit">
        /// The absolute profit.
        /// </param>
        /// <param name="profitRatio">
        /// The profit ratio.
        /// </param>
        /// <param name="hasHighProfitAbsolute">
        /// The has high profit absolute.
        /// </param>
        /// <param name="hasHighProfitPercentage">
        /// The has high profit percentage.
        /// </param>
        /// <param name="exchangeRateProfits">
        /// The exchange rate profits.
        /// </param>
        /// <param name="ruleBreachContext">
        /// The rule breach context.
        /// </param>
        /// <param name="orderUnderAnalysis">
        /// The order under analysis.
        /// </param>
        private void SetJudgementForFullAnalysis(
            Money absoluteProfit,
            decimal profitRatio,
            bool hasHighProfitAbsolute,
            bool hasHighProfitPercentage,
            IExchangeRateProfitBreakdown exchangeRateProfits,
            RuleBreachContext ruleBreachContext,
            Order orderUnderAnalysis)
        {
            var absoluteHighProfit = hasHighProfitAbsolute ? absoluteProfit.Value : (decimal?)null;

            var absoluteHighProfitCurrency = hasHighProfitAbsolute ? absoluteProfit.Currency.Code : null;

            var percentageHighProfit = hasHighProfitPercentage ? profitRatio : (decimal?)null;

            var jsonParameters = JsonConvert.SerializeObject(this.FixedIncomeParameters);
            var judgement      = new FixedIncomeHighProfitJudgement(
                this.RuleCtx.RuleParameterId(),
                this.RuleCtx.CorrelationId(),
                orderUnderAnalysis?.ReddeerOrderId?.ToString(),
                orderUnderAnalysis?.OrderId,
                absoluteHighProfit,
                absoluteHighProfitCurrency,
                percentageHighProfit,
                jsonParameters,
                false,
                false);

            this.JudgementService.Judgement(
                new FixedIncomeHighProfitJudgementContext(
                    judgement,
                    hasHighProfitAbsolute || hasHighProfitPercentage,
                    ruleBreachContext,
                    this.FixedIncomeParameters,
                    absoluteProfit,
                    absoluteProfit.Currency.Symbol,
                    profitRatio,
                    hasHighProfitAbsolute,
                    hasHighProfitPercentage,
                    exchangeRateProfits));
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="FixedIncomeHighProfitJudgementContext"/> class.
 /// </summary>
 /// <param name="judgement">
 /// The judgement.
 /// </param>
 /// <param name="projectToAlert">
 /// The project to alert.
 /// </param>
 /// <param name="ruleBreachContext">
 /// The rule breach context.
 /// </param>
 /// <param name="fixedIncomeParameters">
 /// The fixed income parameters.
 /// </param>
 /// <param name="absoluteProfits">
 /// The absolute profits.
 /// </param>
 /// <param name="absoluteProfitCurrency">
 /// The absolute profit currency.
 /// </param>
 /// <param name="relativeProfits">
 /// The relative profits.
 /// </param>
 /// <param name="hasAbsoluteProfitBreach">
 /// The has absolute profit breach.
 /// </param>
 /// <param name="hasRelativeProfitBreach">
 /// The has relative profit breach.
 /// </param>
 /// <param name="profitBreakdown">
 /// The profit breakdown.
 /// </param>
 public FixedIncomeHighProfitJudgementContext(
     IFixedIncomeHighProfitJudgement judgement,
     bool projectToAlert,
     IRuleBreachContext ruleBreachContext,
     IHighProfitsRuleFixedIncomeParameters fixedIncomeParameters,
     Money?absoluteProfits,
     string absoluteProfitCurrency,
     decimal?relativeProfits,
     bool hasAbsoluteProfitBreach,
     bool hasRelativeProfitBreach,
     IExchangeRateProfitBreakdown profitBreakdown)
 {
     this.Judgement               = judgement;
     this.RaiseRuleViolation      = projectToAlert;
     this.RuleBreachContext       = ruleBreachContext;
     this.FixedIncomeParameters   = fixedIncomeParameters;
     this.AbsoluteProfits         = absoluteProfits;
     this.AbsoluteProfitCurrency  = absoluteProfitCurrency;
     this.RelativeProfits         = relativeProfits;
     this.HasAbsoluteProfitBreach = hasAbsoluteProfitBreach;
     this.HasRelativeProfitBreach = hasRelativeProfitBreach;
     this.ExchangeRateProfits     = profitBreakdown;
 }
예제 #5
0
        /// <summary>
        /// Main method for high profit analysis
        /// </summary>
        /// <param name="history">Trading history qualified for high profit analysis</param>
        /// <param name="intradayCache">Market data for analysis</param>
        protected void EvaluateHighProfits(ITradingHistoryStack history, IUniverseFixedIncomeIntraDayCache intradayCache)
        {
            if (!this.RunRuleGuard(history))
            {
                this.Logger.LogInformation($"EvaluateHighProfits did not pass the rule run guard exiting");

                return;
            }

            var orderUnderAnalysis = this.UniverseEvent.UnderlyingEvent as Order;

            var activeTrades = history.ActiveTradeHistory();

            this.Logger.LogInformation($"EvaluateHighProfits about to filter over Filled with {activeTrades.Count} trades");

            var liveTrades = activeTrades.Where(at => at.OrderStatus() == OrderStatus.Filled).ToList();

            this.Logger.LogInformation($"EvaluateHighProfits about to filter over clean / dirty with {liveTrades.Count} trades");

            var cleanTrades = liveTrades.Where(_ => _.OrderCleanDirty == OrderCleanDirty.CLEAN).ToList();

            this.Logger.LogInformation($"EvaluateHighProfits filtered by clean and had {cleanTrades.Count} trades");

            if (orderUnderAnalysis == null)
            {
                orderUnderAnalysis = activeTrades.LastOrDefault();
            }

            if (!cleanTrades.Any())
            {
                this.Logger.LogInformation($"EvaluateHighProfits had no active and filled trades, exiting");
                this.SetNoLiveTradesJudgement(orderUnderAnalysis);

                return;
            }

            var targetCurrency            = new Currency(this.FixedIncomeParameters.HighProfitCurrencyConversionTargetCurrency);
            var allTradesInCommonCurrency = this.CheckTradesInCommonCurrency(cleanTrades, targetCurrency);
            var costCalculator            = this.GetCostCalculator(allTradesInCommonCurrency, targetCurrency);
            var revenueCalculator         = this.GetRevenueCalculator(allTradesInCommonCurrency, targetCurrency);

            var marketCache =
                this.MarketClosureRule
                    ? this.marketDataCacheFactory.InterdayStrategy(this.UniverseFixedIncomeInterdayCache)
                    : this.marketDataCacheFactory.IntradayStrategy(intradayCache);

            var costTask    = costCalculator.CalculateCostOfPosition(cleanTrades, this.UniverseDateTime, this.RuleCtx);
            var revenueTask = revenueCalculator.CalculateRevenueOfPosition(cleanTrades, this.UniverseDateTime, this.RuleCtx, marketCache);

            var cost            = costTask.Result;
            var revenueResponse = revenueTask.Result;

            if (revenueResponse.HadMissingMarketData)
            {
                this.Logger.LogInformation($"Had missing market data for fixed income high profits, exiting {cleanTrades.FirstOrDefault()?.Instrument?.Identifiers}");
                this.SetMissingMarketDataJudgement(orderUnderAnalysis);
                this.hasMissingData = true;

                return;
            }

            var revenue = revenueResponse.Money;

            if (revenue == null || revenue.Value.Value <= 0)
            {
                this.Logger.LogInformation($"rule had null for revenues for {cleanTrades.FirstOrDefault()?.Instrument?.Identifiers} at {this.UniverseDateTime}. Returning.");
                this.NoRevenueOrCostJudgement(orderUnderAnalysis);

                return;
            }

            if (cost == null || cost.Value.Value <= 0)
            {
                this.Logger.LogInformation(
                    $"We have calculable revenues but not costs for {cleanTrades.FirstOrDefault()?.Instrument?.Identifiers} at {this.UniverseDateTime}. Returning.");
                this.NoRevenueOrCostJudgement(orderUnderAnalysis);

                return;
            }

            if (!revenue.Value.DenominatedInCommonCurrency(cost.Value))
            {
                var convertedCostTask =
                    this.currencyConverterService.Convert(
                        new[] { cost.Value },
                        revenue.Value.Currency,
                        UniverseDateTime,
                        this.RuleCtx);

                var convertedCost = convertedCostTask.Result;

                if (convertedCost == null || !revenue.Value.DenominatedInCommonCurrency(convertedCost.Value))
                {
                    this.Logger.LogError($"Could not convert cost to revenue currency. Expected currency '{revenue.Value.Currency}' but received currency '{convertedCost.Value.Currency}'. For trade {liveTrades.FirstOrDefault()?.Instrument?.Identifiers} at {this.UniverseDateTime}.");
                    return;
                }

                cost = convertedCost;
            }

            this.Logger.LogInformation($"Absolute profit calculating...currency of revenue {revenue.Value.Currency} - currency of costs {cost.Value.Currency} for trade {liveTrades.FirstOrDefault()?.Instrument?.Identifiers} at {this.UniverseDateTime}.");
            var absoluteProfit = revenue.Value - cost.Value;

            this.Logger.LogInformation($"Profit ratio calculating...currency of revenue {revenue.Value.Currency} - currency of costs {cost.Value.Currency} for trade {liveTrades.FirstOrDefault()?.Instrument?.Identifiers} at {this.UniverseDateTime}.");
            var profitRatio = (revenue.Value.Value / cost.Value.Value) - 1;

            this.Logger.LogInformation($"Currency conversion success of revenue {revenue.Value.Currency} - currency of costs {cost.Value.Currency} for trade {liveTrades.FirstOrDefault()?.Instrument?.Identifiers} at {this.UniverseDateTime}.");
            var hasHighProfitAbsolute   = this.HasHighProfitAbsolute(absoluteProfit);
            var hasHighProfitPercentage = this.HasHighProfitPercentage(profitRatio);

            IExchangeRateProfitBreakdown exchangeRateProfits = null;

            if (this.FixedIncomeParameters.UseCurrencyConversions &&
                !string.IsNullOrEmpty(this.FixedIncomeParameters.HighProfitCurrencyConversionTargetCurrency))
            {
                this.Logger.LogInformation(
                    $"is set to use currency conversions and has a target conversion currency to {this.FixedIncomeParameters.HighProfitCurrencyConversionTargetCurrency}. Calling set exchange rate profits.");

                exchangeRateProfits = this.SetExchangeRateProfits(cleanTrades);
            }

            RuleBreachContext ruleBreachContext = null;

            if (hasHighProfitAbsolute || hasHighProfitPercentage)
            {
                this.Logger.LogInformation(
                    $"had a breach for {cleanTrades.FirstOrDefault()?.Instrument?.Identifiers} at {this.UniverseDateTime}. High Profit Absolute {hasHighProfitAbsolute} and High Profit Percentage {hasHighProfitPercentage}.");

                ruleBreachContext = new RuleBreachContext(
                    this.FixedIncomeParameters.Windows.BackwardWindowSize
                    + this.FixedIncomeParameters.Windows.FutureWindowSize,
                    new TradePosition(cleanTrades),
                    cleanTrades.FirstOrDefault(_ => _?.Instrument != null)?.Instrument,
                    this.RuleCtx.IsBackTest(),
                    this.RuleCtx.RuleParameterId(),
                    this.RuleCtx.SystemProcessOperationContext().Id.ToString(),
                    this.RuleCtx.CorrelationId(),
                    this.OrganisationFactorValue,
                    this.FixedIncomeParameters,
                    this.UniverseDateTime);
            }

            this.SetJudgementForFullAnalysis(
                absoluteProfit,
                profitRatio,
                hasHighProfitAbsolute,
                hasHighProfitPercentage,
                exchangeRateProfits,
                ruleBreachContext,
                orderUnderAnalysis);
        }
예제 #6
0
        /// <summary>
        /// The evaluate high profits.
        /// </summary>
        /// <param name="history">
        /// The history.
        /// </param>
        /// <param name="intradayCache">
        /// The intraday cache.
        /// </param>
        protected void EvaluateHighProfits(ITradingHistoryStack history, IUniverseEquityIntraDayCache intradayCache)
        {
            if (!this.RunRuleGuard(history))
            {
                return;
            }

            var orderUnderAnalysis = this.UniverseEvent.UnderlyingEvent as Order;

            var activeTrades = history.ActiveTradeHistory();

            var liveTrades = activeTrades.Where(at => at.OrderStatus() == OrderStatus.Filled).ToList();

            if (orderUnderAnalysis == null)
            {
                orderUnderAnalysis = activeTrades.LastOrDefault();
            }

            if (!liveTrades.Any())
            {
                this.SetNoLiveTradesJudgement(orderUnderAnalysis);

                return;
            }

            var targetCurrency = new Currency(this.EquitiesParameters.HighProfitCurrencyConversionTargetCurrency);

            var allTradesInCommonCurrency = liveTrades.Any() && liveTrades.All(
                x => string.Equals(
                    x.OrderCurrency.Code,
                    targetCurrency.Code,
                    StringComparison.InvariantCultureIgnoreCase));

            var costCalculator    = this.GetCostCalculator(allTradesInCommonCurrency, targetCurrency);
            var revenueCalculator = this.GetRevenueCalculator(allTradesInCommonCurrency, targetCurrency);

            var marketCache = this.MarketClosureRule
                                  ? this.MarketDataCacheFactory.InterdayStrategy(this.UniverseEquityInterdayCache)
                                  : this.MarketDataCacheFactory.IntradayStrategy(intradayCache);

            var costTask    = costCalculator.CalculateCostOfPosition(liveTrades, this.UniverseDateTime, this.RuleContext);
            var revenueTask = revenueCalculator.CalculateRevenueOfPosition(
                liveTrades,
                this.UniverseDateTime,
                this.RuleContext,
                marketCache);

            var cost            = costTask.Result;
            var revenueResponse = revenueTask.Result;

            if (revenueResponse.HadMissingMarketData)
            {
                this.SetMissingMarketDataJudgement(orderUnderAnalysis);
                this.HasMissingData = true;

                return;
            }

            var revenue = revenueResponse.Money;

            if (revenue == null || revenue.Value.Value <= 0)
            {
                this.Logger.LogInformation(
                    $"rule had null for revenues for {liveTrades.FirstOrDefault()?.Instrument?.Identifiers} at {this.UniverseDateTime}. Returning.");

                this.NoRevenueOrCostJudgement(orderUnderAnalysis);
                return;
            }

            if (cost == null || cost.Value.Value <= 0)
            {
                this.Logger.LogError(
                    $"something went wrong. We have calculable revenues but not costs for {liveTrades.FirstOrDefault()?.Instrument?.Identifiers} at {this.UniverseDateTime}. Returning.");

                this.NoRevenueOrCostJudgement(orderUnderAnalysis);
                return;
            }

            if (!revenue.Value.DenominatedInCommonCurrency(cost.Value))
            {
                var convertedCostTask = this.currencyConversionService.Convert(new[] { cost.Value }, revenue.Value.Currency, UniverseDateTime, RuleCtx);
                var convertedCost     = convertedCostTask.Result;

                if (convertedCost == null)
                {
                    this.Logger.LogError($"Currency of revenue {revenue.Value.Currency} - currency of costs {cost.Value.Currency} for trade {liveTrades.FirstOrDefault()?.Instrument?.Identifiers} at {this.UniverseDateTime}.");

                    return;
                }

                cost = convertedCost.Value;
            }

            this.Logger.LogInformation($"Calculating absolute profit Currency of revenue {revenue.Value.Currency} - currency of costs {cost.Value.Currency} for trade {liveTrades.FirstOrDefault()?.Instrument?.Identifiers} at {this.UniverseDateTime}.");
            var absoluteProfit = revenue.Value - cost.Value;

            this.Logger.LogInformation($"Calculating profit ratio Currency of revenue {revenue.Value.Currency} - currency of costs {cost.Value.Currency} for trade {liveTrades.FirstOrDefault()?.Instrument?.Identifiers} at {this.UniverseDateTime}.");
            var profitRatio = revenue.Value.Value / cost.Value.Value - 1;

            this.Logger.LogInformation($"Calculating success profit ratio Currency of revenue {revenue.Value.Currency} - currency of costs {cost.Value.Currency} for trade {liveTrades.FirstOrDefault()?.Instrument?.Identifiers} at {this.UniverseDateTime}.");
            var hasHighProfitAbsolute   = this.HasHighProfitAbsolute(absoluteProfit);
            var hasHighProfitPercentage = this.HasHighProfitPercentage(profitRatio);

            IExchangeRateProfitBreakdown exchangeRateProfits = null;

            if (this.EquitiesParameters.UseCurrencyConversions && !string.IsNullOrEmpty(
                    this.EquitiesParameters.HighProfitCurrencyConversionTargetCurrency))
            {
                this.Logger.LogInformation(
                    $"is set to use currency conversions and has a target conversion currency to {this.EquitiesParameters.HighProfitCurrencyConversionTargetCurrency}. Calling set exchange rate profits.");

                exchangeRateProfits = this.SetExchangeRateProfits(liveTrades);
            }

            RuleBreachContext ruleBreachContext = null;

            if (hasHighProfitAbsolute || hasHighProfitPercentage)
            {
                this.Logger.LogInformation(
                    $"had a breach for {liveTrades.FirstOrDefault()?.Instrument?.Identifiers} at {this.UniverseDateTime}. High Profit Absolute {hasHighProfitAbsolute} and High Profit Percentage {hasHighProfitPercentage}.");

                ruleBreachContext = new RuleBreachContext(
                    this.EquitiesParameters.Windows.BackwardWindowSize
                    + this.EquitiesParameters.Windows.FutureWindowSize,
                    new TradePosition(liveTrades),
                    liveTrades.FirstOrDefault(_ => _?.Instrument != null)?.Instrument,
                    this.RuleContext.IsBackTest(),
                    this.RuleContext.RuleParameterId(),
                    this.RuleContext.SystemProcessOperationContext().Id.ToString(),
                    this.RuleContext.CorrelationId(),
                    this.OrganisationFactorValue,
                    this.EquitiesParameters,
                    this.UniverseDateTime);
            }

            this.SetJudgementForFullAnalysis(
                absoluteProfit,
                profitRatio,
                hasHighProfitAbsolute,
                hasHighProfitPercentage,
                exchangeRateProfits,
                ruleBreachContext,
                orderUnderAnalysis);
        }