internal void ParseFromMarketSellOrderNewHappyFlow() { var order = new OrderUpdate( orderId: 0, tradeId: 0, orderType: Market, orderStatus: New, createdTimestamp: 0, setPrice: 0.4M, side: OrderSide.Sell, pair: TradingPair.Parse("EOSETH"), setQuantity: 40M) { FilledQuantity = 40M, AverageFilledPrice = 0.401M, }; var exec = TradeExecution.FromOrder(order); Assert.Equal(order.Pair.Left, exec.From.Symbol); Assert.Equal(order.Pair.Right, exec.To.Symbol); Assert.Equal(40M, exec.From.Free); Assert.Equal(0, exec.From.Locked); Assert.Equal(40M * 0.401M, exec.To.Free); Assert.Equal(0, exec.To.Locked); }
internal void ParseFromMarketOrderPriceZero(OrderSide side) { var order = new OrderUpdate( orderId: 0, tradeId: 0, orderType: Market, orderStatus: New, createdTimestamp: 0, setPrice: 0.4M, side: side, pair: TradingPair.Parse("EOSETH"), setQuantity: 40M) { AverageFilledPrice = 0M, FilledQuantity = 10M, }; var exec = TradeExecution.FromOrder(order); Assert.Equal(exec.From.Locked, decimal.Zero); if (side == OrderSide.Sell) { Assert.Equal(10M, exec.From.Free); Assert.Equal(decimal.Zero, exec.To.Free); } else { Assert.Equal(decimal.Zero, exec.From.Free); Assert.Equal(10M, exec.To.Free); } Assert.Equal(exec.To.Locked, decimal.Zero); }
/// <summary> /// Queue a trade based on a proposal, the callback must return the trade execution /// which will be used to update the allocation. /// </summary> /// <param name="p">TradeProposal to be verified.</param> /// <param name="tradeCallback">Trade callback to be executed if verification was successful.</param> /// <returns>Boolean indicating successful execution of the callback.</returns> public virtual ResponseObject <OrderUpdate> QueueTrade(TradeProposal p, Func <OrderUpdate> tradeCallback) { Guard.Argument(_allocation).NotNull("Initialise allocations first"); Guard.Argument(p).NotNull(); var alloc = GetAvailableFunds(p.From.Symbol); if (alloc.Free < p.From.Free || alloc.Locked < p.From.Locked) { _logger.LogCritical($"Got trade proposal for ({p.From}, but allocation " + $"showed only ({alloc}) was available\n" + "Trade will not be executed."); return(ResponseObject.OrderRefused); } // Let the provider execute the trade and save the execution report var order = tradeCallback(); // TradingProvider can give a null execution report when it decides not to trade. // if this happens the portfolio will be checked against the remote using an 'empty' or 'monoid' trade execution. if (order is null) { _logger.LogWarning("TradingProvider implementation returned a null OrderUpdate"); return(ResponseObject.OrderPlacementFailed("Implementation returned a null OrderUpdate")); } TradeExecution exec = TradeExecution.FromOrder(order); // Update the local information UpdateAllocation(exec); return(new ResponseObject <OrderUpdate>(order)); }
public void AutoAllocate(TradeExecution te, int randomOrderToExecute) { te.tradedQuantity += randomOrderToExecute; te.remainingOrderQuantity -= randomOrderToExecute; te.status = "Partially Executed"; context.SaveChanges(); }
internal void ParseFromNonMarketBuyOrderForeignCommission(OrderUpdate.OrderTypes type) { var order = new OrderUpdate( orderId: 0, tradeId: 0, orderType: type, orderStatus: Filled, createdTimestamp: 0, setPrice: 0.2M, side: OrderSide.Buy, pair: TradingPair.Parse("EOSETH"), setQuantity: 100M) { FilledQuantity = 100M, AverageFilledPrice = 0.15M, LastFillIncrement = 100M, LastFillPrice = 0.15M, Commission = 96.42M, CommissionAsset = new Currency("BNB"), }; var exec = TradeExecution.FromOrder(order); Assert.Equal(0M, exec.From.Free); Assert.Equal(100M * 0.2M, exec.From.Locked); Assert.Equal(100M, exec.To.Free); Assert.Equal(0M, exec.To.Locked); }
internal void ParseFromNonMarketSellOrderCancelledHappyFlow(OrderUpdate.OrderTypes orderType) { var order = new OrderUpdate( orderId: 0, tradeId: 0, orderType: orderType, orderStatus: Cancelled, createdTimestamp: 0, setPrice: 0.2M, side: OrderSide.Sell, pair: TradingPair.Parse("EOSETH"), setQuantity: 100M); var exec = TradeExecution.FromOrder(order); Assert.NotNull(exec); var symbol = new Currency("EOS"); Assert.Equal(symbol, exec.From.Symbol); Assert.Equal(symbol, exec.To.Symbol); Assert.Equal(0M, exec.From.Free); Assert.Equal(100M, exec.From.Locked); Assert.Equal(100M, exec.To.Free); Assert.Equal(0M, exec.To.Locked); }
public static void AutoAllocate(TradeExecution te, int randomOrderToExecute) { TradeExecution tempTe = context.TradeExecutions.Find(te.tradeId); tempTe.tradedQuantity += randomOrderToExecute; tempTe.remainingOrderQuantity -= randomOrderToExecute; tempTe.status = "Partially"; context.SaveChanges(); }
/// <inheritdoc /> public void UpdateAllocation(TradeExecution exec) { if (Program.CommandLineArgs.Trading) { _logger.LogInformation($"Allocation Update: {JsonConvert.SerializeObject(exec, Formatting.Indented)}"); } _allocation.UpdateAllocation(exec); UpdateObservers(_allocation); }
internal void HandleExecutionMsg(ExecutionMessage msg) { //Add execution TradeExecution tradeExec = new TradeExecution(msg.Execution); //tradeExec.ParentOrderID = this.ID; //tradeExec.Execution = msg.Execution; //tradeExec.Execution.LastLiquidity = null; //tradeExec.Symbol = this.Symbol; HandleTradeExecution(tradeExec); }
private void HandleSellExecution(ParentOrder parentOrder, TradeExecution execution) { TradeOrder order = parentOrder.GetChildOrderByID(execution.OrderID); if (order == null) { Log.Error(string.Format("Cannot find trade order, orderID: {0}", execution.OrderID)); } else { if (string.IsNullOrWhiteSpace(order.Notes)) { Log.Warn("HandleSellExecution error. Cannot resolve execution level due to emtpy order notes"); } else { int exeLevel = int.Parse(order.Notes); TradeMap[exeLevel].CurrentQty -= execution.Shares; if (TradeMap[exeLevel].CurrentQty < 0) { //should not hit here Log.Error(string.Format("Negative CurrentQty detected. level: {0}, qty: {1}", exeLevel, TradeMap[exeLevel].CurrentQty)); } if (TradeMap[exeLevel].CurrentQty <= 0) { if (TradeMap.ContainsKey(CurrentLevel)) { TradeMap[CurrentLevel].WasFilledSellOnPartial = false; TradeMap[CurrentLevel].LastBuyPrice = 0; } CurrentLevel--; //TradeMap.Remove(CurrentLevel); //for (int i = CurrentLevel + 1; i <= ScaleLevel; i++) //{ // if (TradeMap.ContainsKey(i)) TradeMap.Remove(i); //} //if (CurrentLevel >= 0) //{ // GenerateTradeMapNextLevel(TradeMap[CurrentLevel].LastBuyPrice); //} } } Log.Info("After sld execution." + Util.PrintTradeMapCurrLvl(this)); } }
public override void HandleExecutionMsg(ParentOrder parentOrder, TradeExecution tradeExecution) { if (tradeExecution.Side.ToUpper() == Constant.ExecutionBuy) { HandleBuyExecution(parentOrder, tradeExecution); } else if (tradeExecution.Side.ToUpper() == Constant.ExecutionSell) { HandleSellExecution(parentOrder, tradeExecution); } else { Log.Error(string.Format("Unsupported execution. Side {0}", tradeExecution.Side)); } }
internal void ParseFromMarketCancelledOrderInvalid(OrderSide side) { var order = new OrderUpdate( orderId: 0, tradeId: 0, orderType: Market, orderStatus: Cancelled, createdTimestamp: 0, setPrice: 0.2M, side: side, pair: TradingPair.Parse("EOSETH"), setQuantity: 100M); Assert.Throws <ArgumentException>(() => TradeExecution.FromOrder(order)); }
private bool ContainExeution(TradeExecution tradeExec) { bool res = false; foreach (var exe in Executions) { if (exe.ExecID.Trim() == tradeExec.ExecID.Trim()) { res = true; break; } } return(res); }
public void TradeIsProcessedZeroQuantityNewCurrency() { Currency c1 = new Currency("BTC"); Currency c2 = new Currency("ETH"); var trade = new TradeExecution( new Balance(c1, 0, 0), new Balance(c2, 0, 0)); var portfolio = new Portfolio(new Dictionary <Currency, Balance>()); portfolio.UpdateAllocation(trade); Assert.Equal(0M, portfolio.GetAllocation(c1).Free); Assert.Equal(0M, portfolio.GetAllocation(c1).Locked); Assert.Equal(0M, portfolio.GetAllocation(c2).Free); Assert.Equal(0M, portfolio.GetAllocation(c2).Locked); }
public void TradeIsProcessedFreeToLocked() { Currency c1 = new Currency("BTC"); var trade = new TradeExecution( new Balance(c1, 2.0M, 0.0M), new Balance(c1, 0.0M, 2.0M)); var portfolio = new Portfolio(new Dictionary <Currency, Balance>() { { c1, new Balance(c1, 2.5M, 0.0M) }, }); portfolio.UpdateAllocation(trade); Assert.Equal(0.5M, portfolio.GetAllocation(c1).Free); Assert.Equal(2.0M, portfolio.GetAllocation(c1).Locked); }
private void HandleBuyExecution(ParentOrder parentOrder, TradeExecution execution) { /* * check if buy execution create new tradeMap entry * 1.curr level =-1; * 2. Curre level filled and next level exist * 3. curr level partial filled but wasfilled and next level exist * 4. curr level is zero and partial filled and buyback enabled * * */ TradeOrder order = parentOrder.GetChildOrderByID(execution.OrderID); if (order == null) { Log.Error(string.Format("Cannot find trade order, orderID: {0}", execution.OrderID)); } else { int exeLevel = int.Parse(order.Notes); TradeMap[exeLevel].CurrentQty += execution.Shares; if (TradeMap[exeLevel].CurrentQty > TradeMap[exeLevel].TargetQty) { //should not hit here Log.Error(string.Format("Overbot Qty detected. level: {0}, qty: {1}, target qty: {2}", exeLevel, TradeMap[exeLevel].CurrentQty, TradeMap[exeLevel].TargetQty)); } TradeMap[exeLevel].LastBuyPrice = execution.Price; //TradeMap[exeLevel].TargetSellPrice = (exeLevel == 0) ? int.MaxValue : TradeMap[exeLevel - 1].LastBuyPrice; CurrentLevel = Math.Max(CurrentLevel, exeLevel); if (TradeMap[CurrentLevel].Filled) { TradeMap[CurrentLevel].WasFilledSellOnPartial = true; //GenerateTradeMapNextLevel(TradeMap[CurrentLevel].LastBuyPrice); } Log.Info("After bot execution." + Util.PrintTradeMapCurrLvl(this)); } }
internal void ParseFromMarketFilled(OrderSide side) { var order = new OrderUpdate( orderId: 0, tradeId: 0, orderType: Market, orderStatus: Filled, createdTimestamp: 0, setPrice: 0.2M, side: side, pair: TradingPair.Parse("EOSETH"), setQuantity: 100M); var exec = TradeExecution.FromOrder(order); // Assert that the order is calculated as a complete market order Assert.NotEqual(exec.From.Symbol, exec.To.Symbol); Assert.Equal(0M, exec.From.Locked); Assert.Equal(0M, exec.To.Locked); }
public List <TradeExecution> GetTDTradeExecution(TDOrder order) { List <TradeExecution> res = new List <TradeExecution>(); if (order.orderActivityCollection != null) { foreach (var item in order.orderActivityCollection) { if (item.executionLegs != null) { foreach (var leg in item.executionLegs) { TradeExecution exe = new TradeExecution(leg, order); res.Add(exe); } } } } return(res); }
public static void ExecuteOn_Up_Through_ProcessOrderExecution(XComponent.Order.UserObject.OrderExecution orderExecution, object object_PublicMember, object object_InternalMember, Context context, IProcessOrderExecutionOrderExecutionOnUpTradeProcessorSenderInterface sender) { // Execute the existing trade for a revised quantity var tradeExecution = new TradeExecution { AssetName = orderExecution.AssetName, OrderId = orderExecution.OrderId, Price = orderExecution.Price, Quantity = orderExecution.Quantity, RemainingQuantity = orderExecution.RemainingQuantity }; sender.ExecuteTrade(context, tradeExecution); // Create a new trade for the remaining quantity if (orderExecution.RemainingQuantity > 0) { sender.CreateTrade(context, TradeFactory.CreateNewTrade(orderExecution.OrderId, orderExecution.RemainingQuantity, orderExecution.AssetName)); } }
private void UpdateAllocation(OrderUpdate order) { Guard.Argument(order).NotNull(nameof(order)); // Skip Market orders, there are filled at execution time. if (order.OrderType == OrderUpdate.OrderTypes.Market) { return; } // Skip new orders, their allocation is already processed if (order.Status == OrderUpdate.OrderStatus.New) { return; } var exec = TradeExecution.FromOrder(order); _allocationManager.UpdateAllocation(exec); }
internal void ParseFromMarketOrderCommission(OrderSide side) { var order = new OrderUpdate( orderId: 0, tradeId: 0, orderType: Market, orderStatus: Filled, createdTimestamp: 0, setPrice: 0.2M, side: side, pair: TradingPair.Parse("EOSETH"), setQuantity: 100M) { FilledQuantity = 100M, AverageFilledPrice = 0.15M, LastFillIncrement = 100M, LastFillPrice = 0.15M, Commission = 2.3M, CommissionAsset = new Currency("EOS"), }; var exec = TradeExecution.FromOrder(order); if (side == OrderSide.Buy) { Assert.Equal(100M * 0.15M, exec.From.Free); Assert.Equal(100M - 2.3M, exec.To.Free); } else { Assert.Equal(100M, exec.From.Free); Assert.Equal((100M * 0.15M) - (2.3M * 0.15M), exec.To.Free); } Assert.Equal(0, exec.To.Locked); Assert.Equal(0, exec.From.Locked); }
internal void ParseFromLimitFilledDifferentPrice(OrderSide side) { var order = new OrderUpdate( orderId: 0, tradeId: 0, orderType: Limit, orderStatus: Filled, createdTimestamp: 0, setPrice: 0.2M, side: side, pair: TradingPair.Parse("EOSETH"), setQuantity: 100M) { FilledQuantity = 100M, AverageFilledPrice = 0.15M, LastFillIncrement = 100M, LastFillPrice = 0.15M, }; var exec = TradeExecution.FromOrder(order); Assert.Equal(0M, exec.From.Free); if (side == OrderSide.Buy) { // Allocation was locked using the set price, and should be freed as such Assert.Equal(100M * 0.2M, exec.From.Locked); Assert.Equal(100M, exec.To.Free); } else { Assert.Equal(100M, exec.From.Locked); Assert.Equal(100M * 0.15M, exec.To.Free); } Assert.Equal(0, exec.To.Locked); }
private void HandleTradeExecution(TradeExecution tradeExec) { if (ContainExeution(tradeExec)) { Log.Info(string.Format("Received duplicated Execution, ID: {0}, Side: {1}, Qty: {2}, Price: {3}", tradeExec.ExecID, tradeExec.Side, tradeExec.Shares, tradeExec.Price)); return; } lock (locker) { Algo.HandleExecutionMsg(this, tradeExec); Executions.Add(tradeExec); if (tradeExec.Side == Constant.ExecutionBuy) { Qty += tradeExec.Shares; } else if (tradeExec.Side == Constant.ExecutionSell) { Qty -= tradeExec.Shares; } } }
public void Execute() { List <ExternalBlock> blocks = new List <ExternalBlock>(); blocks = context.ExternalBlocks.ToList(); CompareByTime sortBlock = new CompareByTime(); blocks.Sort(sortBlock); Random r1 = new Random(); for (int i = 0; i < blocks.Count; i++) // 10000 -> 1-5000 -> 2222 { // fetching max execution limit for a block // BrokerSecurity bs = new BrokerSecurity(); var x = (from n in context.BrokerSecurities where n.securitySymbol.Equals(blocks[i].symbol) select n).FirstOrDefault(); //fetching market data for the symbol while (blocks[i].openQuantity > 0) { int randomMaxOrderPerIteration = r1.Next(1, x.maxExeOrder); //1-5000 -> 2222 if (randomMaxOrderPerIteration > blocks[i].openQuantity) { randomMaxOrderPerIteration = (int)blocks[i].openQuantity; //make sure that open quantity is not null } while (true) //it's looping only once { int randomOrderToExecute = r1.Next(1, randomMaxOrderPerIteration); // 1-2222 -> 1111 //entering data in trade execution TradeExecution te = new TradeExecution(); te.symbol = blocks[i].symbol; te.tradedQuantity = 0; te.remainingOrderQuantity = randomMaxOrderPerIteration; te.tradePrice = GetTradePrice(blocks[i]); te.blockId = blocks[i].blockId; te.status = "Execution"; te.timestamp = DateTime.Now; //if (blocks[i].createTStamp == null) //{ // te.timestamp = DateTime.Now; //} //else //{ // te.timestamp = (DateTime)blocks[i].createTStamp; //} context.TradeExecutions.Add(te); AutoAllocate(te, randomOrderToExecute); //call auto alocate function with randomOrderToExecute as parameter blocks[i].executedQuantity = randomOrderToExecute; int randomContinueExecution = r1.Next(0, 100); // random value to determine whether to continue if (randomContinueExecution > (100 - x.perFullyExe)) { te.tradedQuantity = randomMaxOrderPerIteration; blocks[i].executedQuantity = randomMaxOrderPerIteration; te.remainingOrderQuantity = 0; te.status = "Fully Executed"; context.SaveChanges(); break; } else { te.status = "Partially Executed"; context.SaveChanges(); break; } } blocks[i].openQuantity -= randomMaxOrderPerIteration; } } }
public abstract void HandleExecutionMsg(ParentOrder parentOrder, TradeExecution tradeExecution);
public static void Execute() { List <ExternalBlock> blocks = new List <ExternalBlock>(); blocks = context.ExternalBlocks.ToList(); CompareByTime sortBlock = new CompareByTime(); blocks.Sort(sortBlock); Random r1 = new Random(); for (int i = 0; i < blocks.Count; i++) // 10000 -> 1-5000 -> 2222 { // fetching max execution limit for a block // BrokerSecurity bs = new BrokerSecurity(); string symbol = blocks[i].symbol; var x = (from n in context.BrokerSecurities where n.securitySymbol.Equals(symbol) select n).FirstOrDefault(); //fetching market data for the symbol while (blocks[i].openQuantity > 0 && !(blocks[i].blockStatus.Equals("Expired"))) { int randomMaxOrderPerIteration = r1.Next(1, x.maxExeOrder); //1-5000 -> 2222 if (randomMaxOrderPerIteration > blocks[i].openQuantity) { randomMaxOrderPerIteration = (int)blocks[i].openQuantity; //make sure that open quantity is not null } //while(true) //it's looping only once int randomOrderToExecute = r1.Next(1, randomMaxOrderPerIteration); // 1-2222 -> 1111 //entering new data in trade execution decimal tempTradePrice = GetTradePrice(blocks[i]); //check for price match int priceMatchStatus = CheckPriceMatch(tempTradePrice, blocks[i]); if (priceMatchStatus == -1) { continue; } TradeExecution te = new TradeExecution(); te.symbol = blocks[i].symbol; te.tradedQuantity = 0; te.remainingOrderQuantity = randomMaxOrderPerIteration; te.tradePrice = tempTradePrice; te.blockId = blocks[i].blockId; te.status = "Execution"; te.timestamp = DateTime.Now; blocks[i].updatedTStamp = te.timestamp; x.tradePrice = tempTradePrice; context.TradeExecutions.Add(te); context.SaveChanges(); AutoAllocate(te, randomOrderToExecute); //call auto alocate function with randomOrderToExecute as parameter int randomContinueExecution = r1.Next(0, 100); // random value to determine whether to continue if (randomContinueExecution > (100 - x.perFullyExe)) { TradeExecution Te = context.TradeExecutions.Find(te.tradeId); Te.tradedQuantity = randomMaxOrderPerIteration; Te.remainingOrderQuantity = 0; blocks[i].executedQuantity += randomMaxOrderPerIteration; Te.remainingOrderQuantity = 0; Te.status = "Fully"; // context.SaveChanges(); //break; } else { TradeExecution Te = context.TradeExecutions.Find(te.tradeId); Te.status = "Partially"; blocks[i].executedQuantity += randomOrderToExecute; // context.SaveChanges(); //break; } blocks[i].openQuantity -= randomMaxOrderPerIteration; if (blocks[i].executedQuantity == blocks[i].totalQuantity) { blocks[i].blockStatus = "Fully"; } else { blocks[i].blockStatus = "Partial"; } context.SaveChanges(); } blocks[i].openQuantity = blocks[i].totalQuantity - blocks[i].executedQuantity; context.SaveChanges(); } //return 1; //return status }
/// <summary> /// Makes sure that allocation is ignored for tests. /// </summary> /// <param name="exec">exec.</param> public void UpdateAllocation(TradeExecution exec) => Expression.Empty();
private void UpdateTradeMapCurrentLevel(TradeExecution execution) { //TradeMapEntry entry = TradeMap[execution] //entry.LastBuyPrice = execution.Execution.Price; //entry.TargetSellPrice = (CurrentLevel == 0) ? int.MaxValue : TradeMap[CurrentLevel - 1].LastBuyPrice; }