public async Task WeightedExchangeRate_Two_Order_With_Unbalanced_Fill() { A.CallTo( () => this._exchangeRatesService.GetRate( A <Currency> .Ignored, A <Currency> .Ignored, DateTime.UtcNow.Date, this._ruleCtx)).Returns( new ExchangeRateDto { DateTime = DateTime.UtcNow, FixedCurrency = "GBP", Name = "abc", Rate = 1, VariableCurrency = "GBP" }); A.CallTo( () => this._exchangeRatesService.GetRate( A <Currency> .Ignored, A <Currency> .Ignored, DateTime.UtcNow.Date.AddDays(1), this._ruleCtx)).Returns( new ExchangeRateDto { DateTime = DateTime.UtcNow, FixedCurrency = "GBP", Name = "abc", Rate = 4, VariableCurrency = "GBP" }); var calculator = new TradePositionWeightedAverageExchangeRateService( this._exchangeRatesService, this._calculatorLogger); var pos1 = new Order().Random(); pos1.OrderFilledVolume = 20; pos1.OrderOrderedVolume = 20; var pos2 = new Order().Random(); pos2.OrderFilledVolume = 10; pos2.OrderOrderedVolume = 10; pos2.AmendedDate = DateTime.UtcNow.Date.AddDays(1); pos2.BookedDate = DateTime.UtcNow.Date.AddDays(1); pos2.CancelledDate = DateTime.UtcNow.Date.AddDays(1); pos2.FilledDate = DateTime.UtcNow.Date.AddDays(1); pos2.PlacedDate = DateTime.UtcNow.Date.AddDays(1); pos2.RejectedDate = DateTime.UtcNow.Date.AddDays(1); var position = new TradePosition(new List <Order> { pos1, pos2 }); var werResult = await calculator.WeightedExchangeRate(position, new Currency("GBP"), this._ruleCtx); Assert.AreEqual(Math.Round(werResult, 2), 2); }
public void ProfitBreakCalculatesCorrectPercentageDueToWer() { var costOne = new Order().Random(); var costTwo = new Order().Random(); var costPosition = new TradePosition(new List <Order> { costOne, costTwo }); var revenueOne = new Order().Random(); var revenueTwo = new Order().Random(); var revenuePosition = new TradePosition(new List <Order> { revenueOne, revenueTwo }); var breakdown = new ExchangeRateProfitBreakdown( costPosition, revenuePosition, 2, 1.5m, new Currency("USD"), new Currency("GBP")); var x = breakdown.AbsoluteAmountDueToWer(); var y = breakdown.RelativePercentageDueToWer(); Assert.AreEqual(x, -1000); Assert.AreEqual(y, -0.25m); }
public async Task WeightedExchangeRate_One_Order_With_One_Fill_Volume_() { A.CallTo( () => this._exchangeRatesService.GetRate( A <Currency> .Ignored, A <Currency> .Ignored, A <DateTime> .Ignored, this._ruleCtx)).Returns( new ExchangeRateDto { DateTime = DateTime.UtcNow, FixedCurrency = "GBP", Name = "abc", Rate = 1, VariableCurrency = "GBP" }); var calculator = new TradePositionWeightedAverageExchangeRateService( this._exchangeRatesService, this._calculatorLogger); var pos1 = new Order().Random(); pos1.OrderFilledVolume = 1; pos1.OrderOrderedVolume = 1; var position = new TradePosition(new List <Order> { pos1 }); var werResult = await calculator.WeightedExchangeRate(position, new Currency("GBP"), this._ruleCtx); Assert.AreEqual(werResult, 1); }
/// <summary> /// The record rule breach. /// </summary> /// <param name="lastTrade"> /// The last trade. /// </param> /// <param name="alignedSentiment"> /// The aligned sentiment. /// </param> /// <param name="opposingSentiment"> /// The opposing sentiment. /// </param> private void RecordRuleBreach(Order lastTrade, IPortfolio alignedSentiment, IPortfolio opposingSentiment) { this.logger.LogInformation($"rule breach detected for {lastTrade.Instrument?.Identifiers}"); var tradingPosition = new TradePosition(alignedSentiment.Ledger.FullLedger().ToList()); var opposingPosition = new TradePosition(opposingSentiment.Ledger.FullLedger().ToList()); // wrong but should be a judgement anyway var ruleBreach = new SpoofingRuleBreach( this.OrganisationFactorValue, this.ruleContext.SystemProcessOperationContext(), this.ruleContext.CorrelationId(), this.equitiesParameters.Windows?.BackwardWindowSize ?? TimeSpan.FromMinutes(30), tradingPosition, opposingPosition, lastTrade.Instrument, lastTrade, this.equitiesParameters, null, null, this.UniverseDateTime); var alert = new UniverseAlertEvent(Rules.Spoofing, ruleBreach, this.ruleContext); this.alertStream.Add(alert); }
public void AddRuleViolationRuleBreachAddsToRuleBreachRepository() { var ruleViolationService = new RuleViolationService( this.queueCasePublisher, this.ruleBreachRepository, this.ruleBreachOrdersRepository, this.ruleBreachToRuleBreachOrdersMapper, this.ruleBreachToRuleBreachMapper, this.logger); var tradePosition = new TradePosition(new List <Order> { OrderHelper.Orders(OrderStatus.Filled) }); A.CallTo(() => this.ruleBreach.Trades).Returns(tradePosition); A.CallTo(() => this.ruleBreach.RuleParameters.TunedParameters).Returns(null); A.CallTo(() => this.ruleBreachRepository.Create(A <RuleBreach> .Ignored)).Returns(100); ruleViolationService.AddRuleViolation(this.ruleBreach); ruleViolationService.ProcessRuleViolationCache(); A.CallTo(() => this.ruleBreachToRuleBreachMapper.RuleBreachItem(this.ruleBreach)) .MustHaveHappenedOnceExactly(); A.CallTo(() => this.ruleBreachRepository.Create(A <RuleBreach> .Ignored)).MustHaveHappenedOnceExactly(); A.CallTo( () => this.ruleBreachToRuleBreachOrdersMapper.ProjectToOrders( A <IRuleBreach> .Ignored, A <string> .Ignored)).MustHaveHappenedOnceExactly(); A.CallTo(() => this.ruleBreachRepository.HasDuplicate(A <string> .Ignored)).MustHaveHappenedOnceExactly(); A.CallTo(() => this.queueCasePublisher.Send(A <CaseMessage> .Ignored)).MustHaveHappenedOnceExactly(); }
/// <summary> /// The pass judgement for daily breach async. /// </summary> /// <param name="mostRecentTrade"> /// The most recent trade. /// </param> /// <param name="tradePosition"> /// The trade position. /// </param> /// <param name="dailyAnalysis"> /// The daily Analysis. /// </param> /// <returns> /// The <see cref="Task"/>. /// </returns> private async Task PassJudgementForDailyBreachAsync( Order mostRecentTrade, TradePosition tradePosition, FixedIncomeHighVolumeJudgement.BreachDetails dailyAnalysis) { var serialisedParameters = JsonConvert.SerializeObject(this.parameters); var judgement = new FixedIncomeHighVolumeJudgement( mostRecentTrade?.Market, this.RuleCtx.RuleParameterId(), this.RuleCtx.CorrelationId(), mostRecentTrade?.ReddeerOrderId?.ToString(), mostRecentTrade?.OrderId?.ToString(), serialisedParameters, this.hadMissingMarketData, false, FixedIncomeHighVolumeJudgement.BreachDetails.None(), dailyAnalysis); var fixedIncomeHighVolumeContext = new FixedIncomeHighVolumeJudgementContext( judgement, true, tradePosition, mostRecentTrade?.Market); await this.judgementService.Judgement(fixedIncomeHighVolumeContext); }
private void ProcessExitPosition(TradePosition position, Entity.Indicator ind, bool isStop) { TradeOrder order = toBll.CreateExitOrder(position, ind, isStop); Transaction tr = trBll.CreateTransaction(order, ind); TradePosition tp = tpBll.UpdateExitPosition(position, tr, order, ind); AccountBalance ab = abBll.ApplyExitTransaction(tr, order, tp); }
/// <summary> /// The run post order event. /// </summary> /// <param name="history"> /// The history. /// </param> protected override void RunPostOrderEvent(ITradingHistoryStack history) { var activeTrades = history.ActiveTradeHistory(); if (!activeTrades.Any()) { return; } var liveTrades = this.FilterByClientAccount( history.ActiveTradeHistory().Pop(), history.ActiveTradeHistory()); if (!liveTrades?.Any() ?? true) { return; } var tradePosition = new TradePosition( this.FilterByClientAccount(history.ActiveTradeHistory().Pop(), history.ActiveTradeHistory())); // Net change analysis var averagePositionCheckTask = this.NettingTrades(liveTrades); averagePositionCheckTask.Wait(); var averagePositionCheck = averagePositionCheckTask.Result; // Clustering trade analysis var clusteringPositionCheck = this.ClusteringTrades(liveTrades); if ((averagePositionCheck == null || !averagePositionCheck.AveragePositionRuleBreach) && (clusteringPositionCheck == null || !clusteringPositionCheck.ClusteringPositionBreach)) { return; } var security = liveTrades?.FirstOrDefault()?.Instrument; this.logger.LogInformation( $"incrementing alerts because of security {security?.Name} at {this.UniverseDateTime}"); // wrong but should be a judgement anyway var breach = new WashTradeRuleBreach( this.equitiesParameters.Windows.BackwardWindowSize, this.OrganisationFactorValue, this.RuleCtx.SystemProcessOperationContext(), this.RuleCtx.CorrelationId(), this.equitiesParameters, tradePosition, security, averagePositionCheck, clusteringPositionCheck, null, null, this.UniverseDateTime); var universeAlert = new UniverseAlertEvent(Rules.WashTrade, breach, this.RuleCtx); this.alertStream.Add(universeAlert); }
private void CalculateOrder(TradeOrder order, TradePosition position) { var account = new AccountBLL(_unit).GetByID(order.AccountId); var broker = new BrokerBLL(_unit).GetByID(account.BrokerId); if (IsReverse(order, position)) { if (IsReverseExceed(order, position)) { int sizeDiff = GetSizeDiff(order, position); order.Fee = GetFee(order.Size * order.OrderPrice, broker); order.Reserve = sizeDiff * order.OrderPrice * Global.MarginRate + order.Fee; } else { order.Fee = GetFee(order.OrderValue, broker); order.Reserve = 0; } } else { order.Fee = GetFee(order.OrderValue, broker); order.Reserve = order.OrderValue * Global.MarginRate + order.Fee; } }
private void ExecuteTradeCloseCommand() { lock (lockTrades) { TradePosition currPosition = TradesCollectionView.CurrentItem as TradePosition; ClientService.GetInstance().requestTradeClosure(currPosition.OrderId); } }
private void PostTransactionProcess(TradeOrder order, Transaction tr, TradePosition tp, Entity.Indicator ind) { order.ProcessedTradingDate = ind.TradingDate; order.Status = "Fulfilled"; toBll.Update(order); }
public PendingTradeParams(TradePosition position, double quantity, double price, PriceTypeEnum priceType, QuantityTypeEnum quantityType) { Position = position; Quantity = quantity; Price = price; PriceType = priceType; QuantityType = quantityType; }
public IReadOnlyCollection <PositionClusterCentroid> Cluster(IReadOnlyCollection <Order> frames) { if (frames == null || !frames.Any()) { return(new PositionClusterCentroid[0]); } var filteredFrames = frames.Where(fra => fra.OrderAverageFillPrice != null && fra.OrderFilledVolume > 0) .ToList(); if (!filteredFrames.Any()) { return(new PositionClusterCentroid[0]); } var clusterCount = this.OptimalClusterCount(frames); var kMeans = new KMeans(clusterCount) { Distance = new WeightedSquareEuclidean(new[] { 2, 0.3 }) }; var prices = filteredFrames.Select( ff => new[] { (double)ff.OrderAverageFillPrice.GetValueOrDefault().Value, ff.MostRecentDateEvent().Ticks }).ToArray(); var clusters = kMeans.Learn(prices); var labels = clusters.Decide(prices); var groupedFrames = filteredFrames.Select((x, i) => new KeyValuePair <int, Order>(i, x)) .GroupBy(i => labels[i.Key]); var results = new List <PositionClusterCentroid>(); foreach (var grp in groupedFrames) { var centroid = clusters.Centroids[labels[grp.First().Key]]; var grpFrames = grp.Select(i => i.Value).ToList(); var buys = new TradePosition( grpFrames.Where( i => i.OrderDirection == OrderDirections.BUY || i.OrderDirection == OrderDirections.COVER) .ToList()); var sells = new TradePosition( grpFrames.Where( i => i.OrderDirection == OrderDirections.SELL || i.OrderDirection == OrderDirections.SHORT) .ToList()); if (buys.Get().Any() && sells.Get().Any()) { var positionCluster = new PositionClusterCentroid((decimal)centroid[0], buys, sells); results.Add(positionCluster); } } return(results); }
public Order(OrderId id, Market market, Pair pair, double quantity, double price, TradePosition position, DateTime?opened) { Id = id; Market = market; Pair = pair; Quantity = quantity; Price = price; Position = position; Opened = opened; }
/// <summary> /// The run initial submission event. /// </summary> /// <param name="history"> /// The history. /// </param> protected override void RunInitialSubmissionEvent(ITradingHistoryStack history) { var tradeWindow = history?.ActiveTradeHistory(); if (tradeWindow == null || !tradeWindow.Any()) { return; } if (tradeWindow.All(trades => trades.OrderDirection == tradeWindow.First().OrderDirection)) { return; } var mostRecentTrade = tradeWindow.Pop(); if (mostRecentTrade.OrderStatus() != OrderStatus.Filled) { return; } var buyPosition = new TradePosition(new List <Order>()); var sellPosition = new TradePosition(new List <Order>()); this.AddToPositions(buyPosition, sellPosition, mostRecentTrade); var tradingPosition = (mostRecentTrade.OrderDirection == OrderDirections.BUY || mostRecentTrade.OrderDirection == OrderDirections.COVER) ? buyPosition : sellPosition; var opposingPosition = (mostRecentTrade.OrderDirection == OrderDirections.SELL || mostRecentTrade.OrderDirection == OrderDirections.SHORT) ? buyPosition : sellPosition; var layeringRuleBreach = this.CheckPositionForLayering( tradeWindow, buyPosition, sellPosition, tradingPosition, opposingPosition, mostRecentTrade); if (layeringRuleBreach != null) { this.logger.LogInformation($"RunInitialSubmissionRule had a breach for {mostRecentTrade?.Instrument?.Identifiers}. Passing to alert stream."); var universeAlert = new UniverseAlertEvent(Domain.Surveillance.Scheduling.Rules.Layering, layeringRuleBreach, this.ruleContext); this.alertStream.Add(universeAlert); } }
public MarketHistory(Pair pair, string id, DateTime timeStamp, double quantity, double price, double total, TradePosition orderType) { Pair = pair; Id = id; TimeStamp = timeStamp; Quantity = quantity; Price = price; Total = total; OrderType = orderType; }
public double GetTransactionDiff(Transaction tr, TradePosition tp) { double diff = 0; if (tr != null && tp != null) { diff = (tp.CurrentPrice - tr.Price) * tr.Size * tr.Flag; } return(diff); }
private void ProcessEntryOrder(TradeOrder order, Entity.Indicator ind) { Transaction tr = trBll.CreateTransaction(order, ind); TradePosition tp = tpBll.CreateEntryPosition(tr, order, ind); AccountBalance ab = abBll.ApplyEntryTransaction(tr, order, tp); this.PostTransactionProcess(order, tr, tp, ind); new AccountBalanceJourneyBLL(_unit).AddJourneyTransaction(ab, "T." + tr.Direction, tr); }
public bool IsReverse(TradeOrder order, TradePosition position) { bool isReverse = false; if (position != null && ((position.Size > 0 && order.Flag < 0) || (position.Size < 0 && order.Flag > 0))) { isReverse = true; } return(isReverse); }
/// <summary> /// The run post order event. /// </summary> /// <param name="history"> /// The history. /// </param> protected override void RunPostOrderEvent(ITradingHistoryStack history) { var tradeWindow = history?.ActiveTradeHistory(); if (tradeWindow == null || !tradeWindow.Any()) { return; } var tradedSecurities = tradeWindow .Where(tr => tr.OrderFilledVolume.GetValueOrDefault() > 0) .ToList(); var tradedVolume = tradedSecurities.Sum(tr => tr.OrderFilledVolume.GetValueOrDefault(0)); var tradePosition = new TradePosition(tradedSecurities.ToList()); var mostRecentTrade = tradeWindow.Peek(); var dailyBreach = this.CheckDailyVolume(mostRecentTrade, tradedVolume); var windowBreach = this.CheckWindowVolume(mostRecentTrade, tradedVolume); var marketCapBreach = this.CheckMarketCap(mostRecentTrade, tradedSecurities); if (this.HasNoBreach(dailyBreach, windowBreach, marketCapBreach)) { return; } // wrong should use a judgement var breach = new HighVolumeRuleBreach( this.OrganisationFactorValue, this.RuleCtx.SystemProcessOperationContext(), this.RuleCtx.CorrelationId(), this.EquitiesParameters?.Windows?.BackwardWindowSize ?? TimeSpan.FromDays(1), tradePosition, mostRecentTrade?.Instrument, this.EquitiesParameters, dailyBreach, windowBreach, marketCapBreach, tradedVolume, null, null, this.UniverseDateTime); this.Logger.LogInformation($"RunRule had a breach for {mostRecentTrade?.Instrument?.Identifiers}. Daily Breach {dailyBreach?.HasBreach} | Window Breach {windowBreach?.HasBreach} | Market Cap Breach {marketCapBreach?.HasBreach}. Passing to alert stream."); var message = new UniverseAlertEvent(Domain.Surveillance.Scheduling.Rules.HighVolume, breach, this.RuleCtx); this.AlertStream.Add(message); }
private int GetPositionStartDate(TradePosition position) { Transaction tr = trBll.GetByID(position.EntryTransactionId); int startDate = tr.TradingDate; if (position.LastProcessedDate.HasValue) { startDate = DateHelper.NextTradingDay(position.LastProcessedDate.Value); } return(startDate); }
private void ExecuteRejectSelectedTradeCommand() { lock (lockTrades) { TradePosition position = PendingTradesCollectionView.CurrentItem as TradePosition; if (position == null) { //todo show error return; } DealerService.GetInstance().approveRejectOrder(position.ClientName, position.OrderId, DealerService.COMMAND_VERB_REJECT); } }
private void ExecuteBulkRejectSelectedTradeCommand() { lock (lockTrades) { foreach (var row in PendingTradesCollectionView) { TradePosition position = row as TradePosition; if (position.IsSelected) { DealerService.GetInstance().approveRejectOrder(position.ClientName, position.OrderId, DealerService.COMMAND_VERB_REJECT); } } } }
/// <summary> /// Выполнить операцию BUY/SELL /// </summary> /// <param name="tradePosition"></param> /// <returns></returns> public override async Task PerformBuyOrSell(TradePosition tradePosition) { var options = tradePosition.Options as EasyTradeOptions; tradePosition.IsStateChanged = false; MarketOrder marketOrder = null; if (tradePosition.PrevOperationType == OperationType.Buy) { //текущая цена превысила ProfitThreshold (цена подскочила, продадим) //или упала на StopLossThreshold (продаем пока ещё больше не упало) if (options != null && (tradePosition.LastPrice >= options.ProfitThreshold || tradePosition.LastPrice <= options.StopLossThreshold)) { marketOrder = new MarketOrder(tradePosition.PortfolioPosition.Figi, tradePosition.PortfolioPosition.Lots, OperationType.Sell, AccountId); tradePosition.IsStateChanged = true; } } else if (tradePosition.PrevOperationType == OperationType.Sell) { //хорошая цена , надо покупать (докупать) if (options != null && tradePosition.LastPrice <= options.DipThreshold /*|| tradePosition.LastPrice >= options.UpwardTrendThreshold*/) { //TODO: здесь надо вычислять сколько лотов можем купить marketOrder = new MarketOrder(tradePosition.PortfolioPosition.Figi, 1, OperationType.Buy, AccountId); tradePosition.IsStateChanged = true; } } if (tradePosition.IsStateChanged && marketOrder != null) { var placedMarketOrder = await Context.PlaceMarketOrderAsync(marketOrder); TradeOperationInfo tradeOperationInfo = new TradeOperationInfo(); tradeOperationInfo.MarketOrder = marketOrder; tradeOperationInfo.PlacedMarkedOrder = placedMarketOrder; ActionOperation?.BeginInvoke(tradeOperationInfo, null, null); } }
private List <Entity.Indicator> GetIndicatorsForTrade(TradePosition position, int dateToProcess) { List <Entity.Indicator> iList = new List <Entity.Indicator>(); int startDate = this.GetPositionStartDate(position); IndicatorBLL iBll = new IndicatorBLL(_unit); iList = iBll.GetIndicatorListByShareDate(position.ShareId, startDate, dateToProcess).OrderByDescending(p => p.TradingDate).ToList(); List <Ticker> tList = new TickerBLL(_unit).GetTickerListByShareDB(position.ShareId, startDate, dateToProcess).OrderByDescending(p => p.TradingDate).ToList(); iBll.PopulateIndicatorsWithTickers(iList, tList); return(iList.OrderBy(p => p.TradingDate).ToList()); }
public bool IsReverseExceed(TradeOrder order, TradePosition position) { bool isExceed = false; if (position != null && ((position.Size > 0 && order.Flag < 0) || (position.Size < 0 && order.Flag > 0))) { if (order.Size > Math.Abs(position.Size)) { isExceed = true; } } return(isExceed); }
public Task SetOptionsTradingPosition(TradePosition tradePosition) { EasyTradeOptions easyTradeOptions = new EasyTradeOptions(); //порог изменения цены, который влияет на пересмотр настроек decimal diffThreshold = _diffPercent * (tradePosition.AvgPrice / 100); easyTradeOptions.DipThreshold = tradePosition.LastPrice - diffThreshold * 1.5m; easyTradeOptions.StopLossThreshold = tradePosition.LastPrice - diffThreshold; easyTradeOptions.UpwardTrendThreshold = tradePosition.LastPrice + diffThreshold; easyTradeOptions.ProfitThreshold = tradePosition.LastPrice + diffThreshold; tradePosition.Options = easyTradeOptions; return(Task.CompletedTask); }
public override bool closeShort(string instrument) { TradePosition lastShort = pairData[instrument].lastShortPosition; if (lastShort != null) { lastShort.timestampClose = now; lastShort.priceClose = getAsk(instrument); pairData[instrument].oldPositions.Add(lastShort); pairData[instrument].lastShortPosition = null; return(true); } else { return(false); } }
public override bool closeLong(string instrument) { TradePosition lastLong = pairData[instrument].lastLongPosition; if (lastLong != null) { lastLong.timestampClose = now; lastLong.priceClose = getBid(instrument); pairData[instrument].oldPositions.Add(lastLong); pairData[instrument].lastLongPosition = null; return(true); } else { return(false); } }
private Dictionary <string, TradePosition> CalculateFloatingStatus(Dictionary <string, List <TradePosition> > receivedPositions) { Dictionary <string, TradePosition> ret = new Dictionary <string, TradePosition>(); string key = string.Empty; foreach (var l in receivedPositions.Values) { foreach (var p in l) { key = p.Commodity; if (!ret.ContainsKey(key)) { ret[key] = new TradePosition() { Commodity = p.Commodity }; } } } foreach (var l in receivedPositions.Values) { foreach (var p in l) { key = p.Commodity; if (p.OrderType.Equals(TradePosition.ORDER_TYPE_BUY)) { ret[key].SumBuyAmt += p.Amount; ret[key].SumPlBuy += p.CurrentPl; ret[key].SumBuyPrice += p.OpenPrice; ret[key].BuysIn++; } else { ret[key].SumSellAmt += p.Amount; ret[key].SumPlSell += p.CurrentPl; ret[key].SumSellPrice += p.OpenPrice; ret[key].SellsIn++; } } } return(ret); }