/// <summary> /// trigger if balance is smaller then 50 /// </summary> public void ManageStopOuts() { cleanUp = clientBalances.Connect(dssds => dssds.BalanceLeft < 80) // .Synchronize(myTrade_locker) .WhereReasonsAre(ChangeReason.Add, ChangeReason.Update) //TODO ADD FILTER - total possition > 0 - to go hear agregated possition of the customer should be > then 0 //.Filter(f => f.BalanceLeft < 80) .Subscribe( c => { foreach (var item in c) { LogInfo("Check if we can clos POSITION check - BALANCE IS BELOW 50 for client: " + item.Current.ClientID + " item.Current.BalanceLeft:" + item.Current.BalanceLeft + " reson" + item.Reason.ToString()); var positionSToclose = curPairPositionPerClient.Items.Where(r => (r.ClientId == item.Current.ClientID && r.Amount1 != 0)).OrderByDescending(d => currencyConverterService.ConvertToBaseCcy(d.Amount1, d.Cur1)); //; if (positionSToclose.Count() > 0) { var positionToclose = positionSToclose.First(); LogInfo("CLOSE THE POSITION - " + positionToclose); double lastquote = 0; if (positionToclose.Amount1 > 0) { lastquote = quotes.Items.Where(r => r.Pair == positionToclose.Pair).First().Bid; } else { lastquote = quotes.Items.Where(r => r.Pair == positionToclose.Pair).First().Ask; } Trade GenerateClosingTrade = new Trade { //Id = myTrades.Count, ClientId = positionToclose.ClientId, Pair = positionToclose.Pair, Amount1 = positionToclose.Amount1 * (-1), Status = Status.Pending, //Status = Status.Open, OpenPrice = lastquote, CurrentPrice = lastquote, Amount2 = positionToclose.Amount1 * (-1) * lastquote, Cur1 = positionToclose.Pair.Substring(0, 3), Cur2 = positionToclose.Pair.Substring(positionToclose.Pair.Length - 3, 3), }; tradesModifierService.AddMyTrade(GenerateClosingTrade); } } } ); }
/// <summary> /// Caluclate position per currency per customer /// </summary> public void CalculatePosistionPerCurrencyPerCustomer() { //var shared = myTrades.Connect(trade => trade.Status == Status.Open); //var shared2 = myTrades.Connect(trade => trade.Status == Status.Pending); //var customers = shared.DistinctValues(trade => trade.Pair); ////distinct list of currency pairs //var currencypairs = shared.DistinctValues(trade => trade.Status); //var dsds = shared.Except(shared2).Subscribe(); cleanUp = myTrades.Connect(trade => (trade.Status == Status.Open || trade.Status == Status.Pending)) .WhereReasonsAre(ChangeReason.Add, ChangeReason.Remove) .Group(t => t.ClientId) .SubscribeMany(groupedData => { var curpositionpercustomer = //groupedData.Cache.Connect(q => q.ClientId == groupedData.Key) groupedData.Cache.Connect() .QueryWhenChanged(query => { var CurUnionQuery = ((from t in query.Items select new CurPositionPerClient() { ClientIdCur = t.ClientId + "_" + t.Cur1, Cur = t.Cur1, ClientId = t.ClientId, Amount = t.Amount1, })) .Union(((from t in query.Items select new CurPositionPerClient() { ClientIdCur = t.ClientId + "_" + t.Cur2, Cur = t.Cur2, ClientId = t.ClientId, Amount = t.Amount2, }))) ; var CurQuery = ((from t in CurUnionQuery group t by t.Cur into g select new CurPositionPerClient() { ClientIdCur = g.Max(a => a.ClientId) + "_" + g.Key, Cur = g.Key, ClientId = g.Max(a => a.ClientId), Amount = g.Sum(a => a.Amount), AmountInBase = currencyConverter.ConvertToBaseCcy(g.Sum(a => a.Amount), g.Key), })); //curPositionPerClient.AddOrUpdate(CurQuery); foreach (var item in CurQuery) { LogInfo("curPositionPerClient.AddOrUpdate:|" + item); curPositionPerClient.AddOrUpdate(item); } //curPositionPerClient // .Edit(updater => // { // foreach (var item in CurQuery) // { // LogInfo("curPositionPerClient.AddOrUpdate:|" + item); // updater.AddOrUpdate(item); // } // } // ); return(CurQuery); } ) .Subscribe(); //TODO calculate required margin per client - calculation based on NOP - Update customer balances return(new CompositeDisposable(curpositionpercustomer)); }) .Subscribe(); }
public void UpdateAllTradesAndQuotes() { var cleanUp = myTrades.Connect(trade => (trade.Status == Status.Open || trade.Status == Status.Pending)) .Group(t => t.Pair) .SubscribeMany( groupedData => { var locker = new object(); double latestAskPrice = 0; double latestBidPrice = 0; //subscribe to price and update trades with the latest price var priceHasChanged = quotes.Connect(q => q.Pair == groupedData.Key) .Synchronize(locker) .Subscribe( price => { foreach (var newquote in price) { latestAskPrice = newquote.Current.Ask; latestBidPrice = newquote.Current.Bid; //myTrades.Edit(updater => // { foreach (var item in groupedData.Cache.Items) { var trade = item; if (trade.Amount1 > 0) { trade.CurrentPrice = latestBidPrice; } else { trade.CurrentPrice = latestAskPrice; } var Profitloss_in_quoted = (trade.OpenPrice - trade.CurrentPrice) * trade.Amount1; // Update P&L on the trade trade.ProfitLoss = currencyConverter.ConvertToBaseCcy(Profitloss_in_quoted, trade.Cur2); myTradesQuoteUpdate.AddOrUpdate(trade); } // } //); } } ); //connect to data changes and update with the latest price var dataHasChanged = groupedData.Cache.Connect() //.WhereReasonsAre(ChangeReason.Add, ChangeReason.Update) .Synchronize(locker) .Subscribe(changes => { foreach (var item in changes) { var trade = item.Current; if (trade.Amount1 > 0) { trade.CurrentPrice = latestBidPrice; } else { trade.CurrentPrice = latestAskPrice; } var Profitloss_in_quoted = (trade.OpenPrice - trade.CurrentPrice) * trade.Amount1; // Update P&L on the trade trade.ProfitLoss = currencyConverter.ConvertToBaseCcy(Profitloss_in_quoted, trade.Cur2); myTradesQuoteUpdate.AddOrUpdate(trade); } } ); return(new CompositeDisposable(priceHasChanged)); } ) .Subscribe(); }