public static BROKER_ORDER UndecorateBrokerOrder(BrokerOrder ord) { var order = new BROKER_ORDER { RequestID = ord.RequestId, ID = ord.Id, Ticker = ord.Ticker, Instrument = (int)ord.Instrument, Volume = ord.Volume, Side = ord.Side, OrderPricing = (int)ord.OrderPricing, RequestedPrice = ord.RequestedPrice, Slippage = ord.Slippage, Dealer = ord.DealerCode, AccountID = ord.AccountID, ClosingPositionID = ord.ClosingPositionID, TimeCreated = ord.TimeCreated, Magic = ord.Magic, Comment = ord.Comment, ExpertComment = ord.ExpertComment, Markup = ord.MarkupAbs }; return(order); }
public async Task HandlerShouldAddOrder() { // Arrange var expectedPlayer = new BrokerPlayer { PlayerId = Guid.NewGuid() }; var expectedOrder = new BrokerOrder { OrderId = Guid.NewGuid(), ItemId = Guid.NewGuid().ToString(), }; _state.Players.Add(expectedPlayer.PlayerId, expectedPlayer); // Act await _handler.Handle(new OrderCreatedEvent(expectedOrder.OrderId, expectedPlayer) { ItemId = expectedOrder.ItemId, }); // Assert Assert.Equal(expectedOrder.OrderId, _state.Orders.Values.Single().OrderId); Assert.Equal(expectedOrder.ItemId, _state.Orders.Values.Single().ItemId); Assert.Equal(OrderState.Active, _state.Orders.Values.Single().State); Assert.Same(expectedPlayer, _state.Orders.Values.Single().Owner); }
private BrokerOrder vHxhvWlydv(BinaryReader obj0) { BrokerOrder brokerOrder = new BrokerOrder(); brokerOrder.Currency = obj0.ReadString(); brokerOrder.OrderID = obj0.ReadString(); brokerOrder.OrderQty = obj0.ReadDouble(); brokerOrder.OrdStatus = obj0.ReadChar(); brokerOrder.OrdType = obj0.ReadChar(); brokerOrder.Price = obj0.ReadDouble(); brokerOrder.SecurityExchange = obj0.ReadString(); brokerOrder.SecurityType = obj0.ReadString(); brokerOrder.Side = obj0.ReadChar(); brokerOrder.StopPx = obj0.ReadDouble(); brokerOrder.Symbol = obj0.ReadString(); int num = obj0.ReadInt32(); for (int index = 0; index < num; ++index) { string name = obj0.ReadString(); string str = obj0.ReadString(); brokerOrder.AddCustomField(name, str); } return(brokerOrder); }
bool DepositAndCreateTrade(ApplicationUser brokerUser, BrokerOrder order) { // check broker exchange id if (brokerUser.Exchange == null) { _logger.LogError("Failed to get broker exchange id"); return(false); } // create and test backend connection var via = new ViaJsonRpc(_settings.AccessHttpUrl); //TODO: move this to a ViaRpcProvider in /Services (like IWalletProvider) via.BalanceQuery(1); // register new deposit with the exchange backend var amount = order.AmountSend.ToString(); var source = new Dictionary <string, object>(); source["BrokerOrderToken"] = order.Token; var businessId = order.Id; try { via.BalanceUpdateQuery(brokerUser.Exchange.Id, order.AssetSend, "deposit", businessId, amount, source); } catch (ViaJsonException ex) { if (ex.Err == ViaError.BALANCE_UPDATE__REPEAT_UPDATE) { _logger.LogError(ex, $"broker already made this exchange update - exch id: {brokerUser.Exchange.Id}, business id: {businessId}"); } else { throw; } } // make trade string tradeAmount; if (order.Side == OrderSide.Bid) { tradeAmount = order.AmountReceive.ToString(); } else if (order.Side == OrderSide.Ask) { tradeAmount = order.AmountSend.ToString(); } else { throw new Exception("invalid order side"); } if (!_settings.MarketOrderBidAmountMoney) { via.OrderMarketQuery(brokerUser.Exchange.Id, order.Market, order.Side, tradeAmount, "0", _apiSettings.Broker.BrokerTag, _settings.MarketOrderBidAmountMoney); } else { via.OrderMarketQuery(brokerUser.Exchange.Id, order.Market, order.Side, tradeAmount, "0", _apiSettings.Broker.BrokerTag); } return(true); }
public void SaveProviderMessage(BrokerOrder msg) { using (var ctx = DatabaseContext.Instance.Make()) { var brokOrder = LinqToEntity.UndecorateBrokerOrder(msg); ctx.BROKER_ORDER.Add(brokOrder); ctx.SaveChanges(); } }
public MarketOrder(int id, string ticker, Instrument instrument, int volume, int side, OrderPricing orderPricing, string accountGroupCode) { AccountGroupCode = accountGroupCode; brokerOrder = new BrokerOrder { Id = id, Ticker = ticker, Instrument = instrument, Volume = volume, Side = side, OrderPricing = orderPricing }; }
public async Task HandlerShouldCancelOrder() { // Arrange var initialOrder = new BrokerOrder { OrderId = Guid.NewGuid(), State = OrderState.Active, }; _state.Orders.Add(initialOrder.OrderId, initialOrder); // Act await _handler.Handle(new OrderCancelledEvent(initialOrder.OrderId, null)); // Assert Assert.Equal(OrderState.Cancelled, _state.Orders.Values.Single().State); }
public MarketOrder(int id, string ticker, Instrument instrument, int volume, int side, OrderPricing orderPricing, decimal?requestedPrice, decimal?enabledAbsoluteSlippage, string accountGroupCode) { AccountGroupCode = accountGroupCode; brokerOrder = new BrokerOrder { Id = id, Ticker = ticker, Instrument = instrument, Volume = volume, Side = side, OrderPricing = orderPricing, RequestedPrice = requestedPrice, Slippage = enabledAbsoluteSlippage }; }
public Task Handle(OrderCreatedEvent evnt) { var player = _state.Players[evnt.OwnerId]; var order = new BrokerOrder { OrderId = evnt.EntityId, OwnerId = evnt.OwnerId, ItemId = evnt.ItemId, Quantity = evnt.Quantity, Price = evnt.Price, OrderType = evnt.OrderType, State = OrderState.Active, Owner = player, }; _state.Orders.Add(evnt.EntityId, order); return(Task.CompletedTask); }
private void RoYu8jI0tu(BinaryWriter obj0, BrokerOrder obj1) { obj0.Write(obj1.Currency); obj0.Write(obj1.OrderID); obj0.Write(obj1.OrderQty); obj0.Write(obj1.OrdStatus); obj0.Write(obj1.OrdType); obj0.Write(obj1.Price); obj0.Write(obj1.SecurityExchange); obj0.Write(obj1.SecurityType); obj0.Write(obj1.Side); obj0.Write(obj1.StopPx); obj0.Write(obj1.Symbol); BrokerOrderField[] customFields = obj1.GetCustomFields(); obj0.Write(customFields.Length); foreach (BrokerOrderField brokerOrderField in customFields) { obj0.Write(brokerOrderField.Name); obj0.Write(brokerOrderField.Value); } }
static void AddPendingOrder(LiveOpenPositionsEditor openPositionData, Symbol symbol, string orderId, long size, DateTime submittedTime, OrderType orderType, TransactionType transactionType, double price, string customString) { if (openPositionData.PortfolioXml.PendingOrders.Any(o => o.OrderId == orderId)) { // Order already tracked return; } PositionType positionType = (transactionType == TransactionType.Buy || transactionType == TransactionType.Sell) ? PositionType.Long : PositionType.Short; // This assumes there is just one position per symbol. If this isn't the case then you will need to find a way of figuring out which // position a pending order corresponds to. PositionDataXml position = openPositionData.PortfolioXml.Positions.FirstOrDefault(pos => pos.Symbol.Equals(symbol) && pos.PositionType == positionType); if (position == null) { // No existing position, so create a new one position = openPositionData.AddPosition(symbol, positionType); position.CustomString = customString; } BrokerOrder brokerOrder = new BrokerOrder(); if (orderType == OrderType.Limit || orderType == OrderType.LimitOnClose) { brokerOrder.LimitPrice = price; } else if (orderType == OrderType.Stop || orderType == OrderType.TrailingStop) { brokerOrder.StopPrice = price; } brokerOrder.CustomString = customString; TradeOrderXml tradeOrder = openPositionData.AddPendingOrder(position, brokerOrder, orderId, size, submittedTime, orderType, transactionType); }
public MarketOrder(BrokerOrder brokerOrder) { this.brokerOrder = brokerOrder; }
private IEnumerable <IEvent> EvaluateBuyOrder( BrokerOrder buyOrder, BrokerOrder sellOrder, long quantityToSell, State state) { // The quantity one order can buy will be the least of either: // 1. As much as the buyer can buy (credits) // 2. As much as the seller can sell (inventory/order size) // 3. As much as the buyer wants to buy (order size) if (sellOrder.Price == 0) { yield break; } var affordableQuantity = buyOrder.Owner.Credits / sellOrder.Price; var quantityToBuy = Math.Min(affordableQuantity, quantityToSell); // Case 1 & 2 if (buyOrder.Quantity != -1) // Case 3 { quantityToBuy = Math.Min(quantityToBuy, buyOrder.Quantity - buyOrder.QuantityFulfilled); } var evnt = new OrderTransactionEvent(Guid.NewGuid(), _initiator) { FromPlayer = sellOrder.Owner.PlayerId, ToPlayer = buyOrder.Owner.PlayerId, FromSellOrder = sellOrder.OrderId, ToBuyOrder = buyOrder.OrderId, ItemId = sellOrder.ItemId, Quantity = quantityToBuy, Price = quantityToBuy * sellOrder.Price, }; buyOrder.Owner.Credits -= evnt.Price; sellOrder.Owner.Credits += evnt.Price; buyOrder.QuantityFulfilled += evnt.Quantity; sellOrder.QuantityFulfilled += evnt.Quantity; UpdatePlayerInventory(buyOrder.Owner, evnt.ItemId, evnt.Quantity); UpdatePlayerInventory(sellOrder.Owner, evnt.ItemId, -evnt.Quantity); state.HandledTransactions.Enqueue(evnt.EntityId); yield return(evnt); yield return(new OrderPartiallyFulfilledEvent(buyOrder.OrderId, _initiator) { TransactionId = evnt.EntityId, Price = evnt.Price, QuantityFulfilled = evnt.Quantity, }); yield return(new OrderPartiallyFulfilledEvent(sellOrder.OrderId, _initiator) { TransactionId = evnt.EntityId, Price = evnt.Price, QuantityFulfilled = evnt.Quantity, }); yield return(new PlayerBalanceChangedEvent(buyOrder.Owner.PlayerId, _initiator) { TransactionId = evnt.EntityId, BalanceChange = -evnt.Price, }); yield return(new PlayerBalanceChangedEvent(sellOrder.Owner.PlayerId, _initiator) { TransactionId = evnt.EntityId, BalanceChange = evnt.Price, }); yield return(new PlayerInventoryChangedEvent(buyOrder.Owner.PlayerId, _initiator) { TransactionId = evnt.EntityId, InventoryChange = new[] { new LuaItemStack { Name = evnt.ItemId, Count = evnt.Quantity, }, }, }); yield return(new PlayerInventoryChangedEvent(sellOrder.Owner.PlayerId, _initiator) { TransactionId = evnt.EntityId, InventoryChange = new[] { new LuaItemStack { Name = evnt.ItemId, Count = -evnt.Quantity, }, }, }); if (buyOrder.Quantity != -1 && buyOrder.QuantityFulfilled >= buyOrder.Quantity) { yield return(new OrderFulfilledEvent(buyOrder.OrderId, _initiator)); buyOrder.State = OrderState.Fulfilled; _logger.Information($"Buy order ${buyOrder.OrderId} completely fulfilled!"); } }
void ProcessOrderChain(BrokerOrder order) { // check wallet has been updated var time = _walletProvider.LastBlockchainWalletUpdate(order.AssetSend); if (time < DateTimeOffset.Now.AddMinutes(-(_apiSettings.Broker.TimeLimitGracePeriod / 2))) { _logger.LogWarning($"Not processing broker order ({order.Token}) as the wallet ({order.AssetSend}) was not updated since {time}"); return; } // get broker user var brokerUser = _userManager.FindByNameAsync(_apiSettings.Broker.BrokerTag).GetAwaiter().GetResult(); if (brokerUser == null) { _logger.LogError("Failed to find broker user"); return; } // get order user var user = _userManager.FindByIdAsync(order.ApplicationUserId).GetAwaiter().GetResult(); if (user == null) { _logger.LogError($"Failed to find order user ('{order.ApplicationUserId}')"); return; } if (order.Status == BrokerOrderStatus.Ready.ToString() || order.Status == BrokerOrderStatus.Incomming.ToString()) { CheckTxs(brokerUser, user, order); } else if (order.Status == BrokerOrderStatus.Confirmed.ToString()) { if (FiatWithdrawToCustomer(brokerUser, order)) { order.Status = BrokerOrderStatus.PayoutWait.ToString(); _context.BrokerOrders.Update(order); _logger.LogError($"Sent fiat for order ('{order.Token}')"); } else { _logger.LogError($"failed to send fiat for order ({order.Token})"); } } else if (order.Status == BrokerOrderStatus.PayoutWait.ToString()) { var bow = _context.BrokerOrderFiatWithdrawals.SingleOrDefault(o => o.BrokerOrderId == order.Id); if (bow == null) { _logger.LogWarning($"broker order withdrawal not found ({order.Token})"); return; } // check fiat withdrawal is completed var wallet = _walletProvider.GetFiat(order.AssetReceive); var fiatTx = wallet.GetTx(bow.DepositCode); if (fiatTx != null && fiatTx.BankTx != null) { order.Status = BrokerOrderStatus.Sent.ToString(); _context.BrokerOrders.Update(order); _logger.LogInformation($"Payout confirmed for order {order.Token}"); // send email var sendWallet = _walletProvider.GetChain(order.AssetSend); var receiveWallet = _walletProvider.GetFiat(order.AssetReceive); _emailSender.SendEmailBrokerSentOutgoingFunds(user.Email, order.AssetSend, sendWallet.AmountToString(order.AmountSend), order.AssetReceive, receiveWallet.AmountToString(order.AmountReceive), order.InvoiceId).GetAwaiter().GetResult(); _logger.LogInformation($"Sent email to {user.Email}"); } } }
void ProcessOrderFiat(BrokerOrder order) { if (!_fiatSettings.PaymentsEnabled) { _logger.LogError("receiving fiat not enabled"); return; } if (!_fiatSettings.PaymentsAssets.Contains(order.AssetSend)) { _logger.LogError($"receiving fiat currency '${order.AssetSend}' not supported"); return; } // get broker user var brokerUser = _userManager.FindByNameAsync(_apiSettings.Broker.BrokerTag).GetAwaiter().GetResult(); if (brokerUser == null) { _logger.LogError("Failed to find broker user"); return; } // get order user var user = _userManager.FindByIdAsync(order.ApplicationUserId).GetAwaiter().GetResult(); if (user == null) { _logger.LogError($"Failed to find order user ('{order.ApplicationUserId}')"); return; } var paymentReq = RestUtils.GetFiatPaymentRequest(_fiatSettings, order.Token); if (paymentReq == null) { _logger.LogError($"Failed to get fiat payment request (token: {order.Token})"); return; } if (order.Status == BrokerOrderStatus.Ready.ToString() || order.Status == BrokerOrderStatus.Incomming.ToString()) { // bingo! if (paymentReq.Status.ToLower() == viafront3.Models.ApiViewModels.ApiRequestStatus.Completed.ToString().ToLower()) { order.Status = BrokerOrderStatus.Confirmed.ToString(); _context.BrokerOrders.Update(order); _logger.LogInformation($"Payment confirmed for order {order.Token}"); DepositAndCreateTrade(brokerUser, order); // send email var wallet = _walletProvider.GetFiat(order.AssetSend); if (wallet == null) { _logger.LogError($"Failed to get fiat wallet for order (token: {order.Token})"); return; } _emailSender.SendEmailBrokerSeenIncomingFunds(user.Email, order.AssetSend, wallet.AmountToString(order.AmountSend), order.InvoiceId).GetAwaiter().GetResult(); _logger.LogInformation($"Sent email to {user.Email}"); } } else if (order.Status == BrokerOrderStatus.Confirmed.ToString()) { if (ChainWithdrawToCustomer(brokerUser, order)) { order.Status = BrokerOrderStatus.PayoutWait.ToString(); _context.BrokerOrders.Update(order); _logger.LogInformation($"Sent funds for order {order.Token}"); } else { _logger.LogError($"failed to send funds for order ({order.Token})"); } } else if (order.Status == BrokerOrderStatus.PayoutWait.ToString()) { var bow = _context.BrokerOrderChainWithdrawals.SingleOrDefault(o => o.BrokerOrderId == order.Id); if (bow == null) { _logger.LogWarning($"broker order withdrawal not found ({order.Token})"); return; } var asset = order.AssetReceive; var wallet = _walletProvider.GetChain(asset); if (wallet == null) { _logger.LogError($"No chain wallet for {asset}"); return; } var spend = wallet.PendingSpendsGet().SingleOrDefault(s => s.SpendCode == bow.SpendCode); if (spend == null) { _logger.LogError($"No pending spend for broker {bow.SpendCode}"); return; } if (spend.State == PendingSpendState.Complete) { order.Status = BrokerOrderStatus.Sent.ToString(); order.TxIdRecipient = spend.TxIds; _context.BrokerOrders.Update(order); _logger.LogInformation($"Payout confirmed for order {order.Token}"); // send email var sendWallet = _walletProvider.GetFiat(order.AssetSend); var receiveWallet = _walletProvider.GetChain(order.AssetReceive); _emailSender.SendEmailBrokerSentOutgoingFunds(user.Email, order.AssetSend, sendWallet.AmountToString(order.AmountSend), order.AssetReceive, receiveWallet.AmountToString(order.AmountReceive), order.InvoiceId).GetAwaiter().GetResult(); _logger.LogInformation($"Sent email to {user.Email}"); } } }
private void OnOrderUpdated(BrokerOrder order, Fill fill, string information) { OrderUpdatedDelegate del = _orderUpdated; if (del != null) { del(order, fill, information); } }
public bool FiatWithdrawToCustomer(ApplicationUser brokerUser, BrokerOrder order) { var asset = order.AssetReceive; var amount = order.AmountReceive; var wallet = _walletProvider.GetFiat(asset); if (wallet == null) { _logger.LogError($"No fiat wallet for {asset}"); return(false); } var via = new ViaJsonRpc(_settings.AccessHttpUrl); var balance = via.BalanceQuery(brokerUser.Exchange.Id, asset); // validate amount var amountInt = wallet.AmountToLong(amount); var availableInt = wallet.StringToAmount(balance.Available); if (amountInt > availableInt) { _logger.LogError("broker available balance is too small"); return(false); } if (amountInt <= 0) { _logger.LogError("amount must be greather then or equal to 0"); return(false); } using (var dbtx = wallet.BeginDbTransaction()) { // register withdrawal with wallet var acct = new BankAccount { AccountNumber = order.Recipient }; var tx = wallet.RegisterPendingWithdrawal(brokerUser.Id, amountInt, acct); if (tx == null) { _logger.LogError($"Failed to create fiat withdrawal ('{order.Token}')"); return(false); } wallet.Save(); var businessId = tx.Id; try { // link pending withdrawal to broker order var bow = new BrokerOrderFiatWithdrawal { BrokerOrderId = order.Id, DepositCode = tx.DepositCode }; _context.BrokerOrderFiatWithdrawals.Add(bow); // we save changes here so that we a broker order cannot be processed twice(BrokerOrderChainWithdrawal.BrokerOrderId is unique) _context.SaveChanges(); } catch { _logger.LogError($"unable to create BrokerOrderChainWithdrawal object ({order.Id}, {tx.DepositCode}"); throw; } // register withdrawal with the exchange backend var negativeAmount = -amount; try { via.BalanceUpdateQuery(brokerUser.Exchange.Id, asset, "withdraw", businessId, negativeAmount.ToString(), null); } catch (ViaJsonException ex) { _logger.LogError(ex, "Failed to update (withdraw) user balance (xch id: {0}, asset: {1}, businessId: {2}, amount {3}", brokerUser.Exchange.Id, asset, businessId, negativeAmount); if (ex.Err == ViaError.BALANCE_UPDATE__BALANCE_NOT_ENOUGH) { dbtx.Rollback(); _logger.LogError("balance not enough"); return(false); } throw; } dbtx.Commit(); } return(true); }
//Xem bang này có bảng lịch sử clone từ bảng này ra hay không? public static string GetEntityNameHist(string entityName) { if (entityName == ApprovalAccount.EntityName()) { return(ApprovalAccountHist.EntityName()); } if (entityName == ApprovalDealing.EntityName()) { return(ApprovalDealingHist.EntityName()); } if (entityName == ApprovalMember.EntityName()) { return(ApprovalMemberHist.EntityName()); } if (entityName == ApprovalOrder.EntityName()) { return(ApprovalOrderHist.EntityName()); } if (entityName == ApprovalPreRisk.EntityName()) { return(ApprovalPreRiskHist.EntityName()); } if (entityName == ApprovalSystem.EntityName()) { return(ApprovalSystemHist.EntityName()); } if (entityName == AccountTransaction.EntityName()) { return(AccountTransactionHist.EntityName()); } if (entityName == BrokerOrder.EntityName()) { return(BrokerOrderHist.EntityName()); } if (entityName == ExecutionReport.EntityName()) { return(ExecutionReportHist.EntityName()); } if (entityName == OpenPositionDetail.EntityName()) { return(OpenPositionDetailHist.EntityName()); } if (entityName == OpenPosition.EntityName()) { return(OpenPositionHist.EntityName()); } if (entityName == OrderTransaction.EntityName()) { return(OrderTransactionHist.EntityName()); } if (entityName == SpecAccounting.EntityName()) { return(SpecAccountingHist.EntityName()); } if (entityName == SymbolSettlementPrice.EntityName()) { return(SymbolSettlementPriceDaily.EntityName()); } if (entityName == TradingDeal.EntityName()) { return(TradingDealHist.EntityName()); } return(null); }
public bool SubmitOrder(BrokerOrder order, out string orderId) { VerifyConnected(); order.OrderId = Guid.NewGuid().ToString(); orderId = order.OrderId; // Make sure this symbol is being watched if (!knownSymbols.ContainsKey(order.OrderSymbol)) { //Console.WriteLine("Looking up contract for " + order.OrderSymbol.ToString()); knownSymbols[order.OrderSymbol] = null; StartWatching(); _pendingOrders.Add(order); _openOrderMap[order.OrderId] = order; return true; } ReturnCode ret = InternalSubmitOrder(order); if (!ret.Success) { lastError = ret.Message; orderId = null; return false; } _openOrderMap[order.OrderId] = order; return true; }
public TradeInfo AddCompletedTradeToPosition(PositionDataXml position, DateTime filledTime, TransactionType transactionType, Price price, long size, string orderID) { PositionDataXml brokerPos = GetBrokerPosition(position.Symbol, position.PositionType); // Create a PositionInfo object to calculate the PositionStats, which we can use to calculate a new TradeInfo PositionInfo brokerPosInfo = GetPositionInfo(brokerPos); BrokerOrder order = new BrokerOrder(); order.OrderId = orderID; order.PositionID = position.PosID; order.TransactionType = transactionType; order.OrderType = OrderType.Market; order.OrderSymbol = position.Symbol; Fill fill = new Fill(); fill.FillDateTime = filledTime; fill.Price = price; fill.Quantity = size; fill.Commission = 0; var createPositionTradeMethod = typeof(PositionManager).GetMethod("CreatePositionTrade", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); var argList = new object[] { position.Symbol, brokerPosInfo.CurrentStats, new SymbolAccountInfo(position.Symbol), order, fill, TradeType.UserSubmitted, // Trade type string.Empty // Description }; TradeInfo ret = (TradeInfo)createPositionTradeMethod.Invoke(null, argList); if (position.Trades.Any(t => t.FilledTime == filledTime)) { ret.Sequence = position.Trades.Where(t => t.FilledTime == filledTime).Max(t => t.Sequence) + 1; } else { ret.Sequence = 0; } position.Trades.Add(ret); brokerPos.Trades.Add(ret); PortfolioXml.CurrentPrices[position.Symbol] = price.SymbolPrice; position.IsPending = false; brokerPos.IsPending = false; // If position size is now zero, remove it from the list of open positions if (GetPositionInfo(position).CurrentStats.CurrentSize == 0) { PortfolioXml.Positions.Remove(position); } if (GetPositionInfo(brokerPos).CurrentStats.CurrentSize == 0) { if (brokerPos.PositionType == PositionType.Long) { _longBrokerPositions.Remove(brokerPos.Symbol); } else { _shortBrokerPositions.Remove(brokerPos.Symbol); } } return ret; }
public TradeOrderXml AddPendingOrder(PositionDataXml position, BrokerOrder brokerOrder, string orderId, long size, DateTime submittedTime, OrderType orderType, TransactionType transactionType) { brokerOrder.OrderSymbol = position.Symbol; brokerOrder.OrderId = orderId; brokerOrder.PositionID = position.PosID; brokerOrder.Shares = size; brokerOrder.SubmittedDate = submittedTime; brokerOrder.OrderType = orderType; brokerOrder.TransactionType = transactionType; brokerOrder.OrderState = BrokerOrderState.Submitted; TradeOrderXml ret = new TradeOrderXml(); ret.PosID = position.PosID; ret.OrderID = orderId; ret.TradeType = TradeType.UserSubmitted; ret.Description = string.Empty; ret.Error = null; ret.BarsValid = -1; ret.CancelPending = false; PortfolioXml.PendingOrders.Add(brokerOrder); position.PendingOrders.Add(ret); return ret; }
private ReturnCode InternalSubmitOrder(BrokerOrder order) { OEC.API.OrderDraft draft = oecClient.CreateDraft(); draft.Account = oecClient.Accounts.First; if (order.TransactionType == TransactionType.Buy || order.TransactionType == TransactionType.Cover) { draft.Side = OEC.Data.OrderSide.Buy; } else if (order.TransactionType == TransactionType.Sell || order.TransactionType == TransactionType.Short) { draft.Side = OEC.Data.OrderSide.Sell; } else { throw new RightEdgeError("Transaction type " + order.TransactionType.ToString() + " not supported by broker."); } draft.Quantity = (int)order.Shares; draft.Contract = GetContractFromSymbol(order.OrderSymbol); if (order.OrderType == OrderType.Market) { draft.Type = OEC.Data.OrderType.Market; } else if (order.OrderType == OrderType.MarketOnClose) { draft.Type = OEC.Data.OrderType.MarketOnClose; } else if (order.OrderType == OrderType.MarketOnOpen) { draft.Type = OEC.Data.OrderType.MarketOnOpen; } else if (order.OrderType == OrderType.Limit) { draft.Type = OEC.Data.OrderType.Limit; draft.Price = order.LimitPrice; } else if (order.OrderType == OrderType.Stop) { draft.Type = OEC.Data.OrderType.Stop; draft.Price = order.StopPrice; } else if (order.OrderType == OrderType.StopLimit) { draft.Type = OEC.Data.OrderType.StopLimit; draft.Price = order.StopPrice; draft.Price2 = order.LimitPrice; } //else if (order.OrderType == OrderType.TrailingStop) //{ // draft.Type = OEC.Data.OrderType.TrailingStopLimit; //} else { //throw new RightEdgeError("Order type " + order.OrderType.ToString() + " not supported by broker."); return ReturnCode.Fail("Order type " + order.OrderType.ToString() + " not supported by broker."); } if (order.GoodTillCanceled) { draft.Flags |= OEC.Data.OrderFlags.GTC; } //draft.Flags |= OEC.Data.OrderFlags.AON; OEC.API.OrderParts res = draft.GetInvalidParts(); if (res != OEC.API.OrderParts.None) { string msg = "Invalid order: " + res.ToString(); Trace.WriteLine(msg); //orderId = null; return ReturnCode.Fail(msg); } OEC.API.Order oecOrder = oecClient.SendOrder(draft); _orderIDMap[oecOrder.ID] = order.OrderId; order.OrderState = BrokerOrderState.Submitted; order.SubmittedDate = DateTime.Now; return ReturnCode.Succeed; }
public async Task HandlerShouldHandleTransaction(bool buyerHasExistingInventory) { // Arrange var rng = new Random(); var expectedPrice = rng.Next(); var expectedQuantity = rng.Next(); var expectedItem = Guid.NewGuid().ToString(); var buyer = new BrokerPlayer { PlayerId = Guid.NewGuid(), Inventory = new Dictionary <string, WarehouseInventory>(), }; if (buyerHasExistingInventory) { buyer.Inventory.Add(expectedItem, new WarehouseInventory()); } var seller = new BrokerPlayer { PlayerId = Guid.NewGuid(), Inventory = new Dictionary <string, WarehouseInventory> { { expectedItem, new WarehouseInventory() } } }; var buyOrder = new BrokerOrder { OrderId = Guid.NewGuid(), OrderType = OrderType.Buy, ItemId = expectedItem, Owner = buyer, }; var sellOrder = new BrokerOrder { OrderId = Guid.NewGuid(), OrderType = OrderType.Sell, ItemId = expectedItem, Owner = seller, }; _state.Orders.Add(buyOrder.OrderId, buyOrder); _state.Orders.Add(sellOrder.OrderId, sellOrder); // Act await _handler.Handle(new OrderTransactionEvent(Guid.NewGuid(), null) { FromSellOrder = sellOrder.OrderId, ToBuyOrder = buyOrder.OrderId, Quantity = expectedQuantity, Price = expectedPrice, ItemId = expectedItem, }); // Assert Assert.Equal(-expectedPrice, buyer.Credits); Assert.Equal(expectedPrice, seller.Credits); Assert.Equal(expectedQuantity, buyOrder.QuantityFulfilled); Assert.Equal(expectedQuantity, sellOrder.QuantityFulfilled); Assert.Equal(expectedQuantity, buyer.Inventory[expectedItem].Quantity); Assert.Equal(-expectedQuantity, seller.Inventory[expectedItem].Quantity); }
void CheckTxs(ApplicationUser brokerUser, ApplicationUser user, BrokerOrder order) { // get wallet and only update from the blockchain one time IWallet wallet = _walletProvider.GetChain(order.AssetSend); var txs = wallet.GetAddrUnacknowledgedTransactions(order.PaymentAddress); var ackTxs = new List <WalletTx>(); foreach (var tx in txs) { // get invoice id string invoiceId = null; if (tx.ChainTx.Attachment != null) { var att = System.Text.Encoding.UTF8.GetString(tx.ChainTx.Attachment.Data); try { var dict = JsonConvert.DeserializeObject <Dictionary <string, string> >(att); invoiceId = dict.FirstOrDefault(x => String.Equals(x.Key, "InvoiceId", StringComparison.OrdinalIgnoreCase)).Value; } catch {} } // check tx is incomming to our wallet if (tx.Direction == WalletDirection.Incomming) { // check invoice id matches (if asset uses account model) if (wallet.GetLedgerModel() == xchwallet.LedgerModel.Account && invoiceId == order.InvoiceId || wallet.GetLedgerModel() == xchwallet.LedgerModel.UTXO) { // check amount matches var amount = wallet.AmountToString(tx.AmountOutputs()); if (order.AmountSend <= decimal.Parse(amount)) { // bingo! if (order.Status == BrokerOrderStatus.Ready.ToString()) { order.Status = BrokerOrderStatus.Incomming.ToString(); order.TxIdPayment = tx.ChainTx.TxId; _context.BrokerOrders.Update(order); _logger.LogInformation($"Payment detected for order {order.Token}, {tx}"); // send email _emailSender.SendEmailBrokerSeenIncomingFunds(user.Email, order.AssetSend, wallet.AmountToString(order.AmountSend), order.InvoiceId).GetAwaiter().GetResult(); _logger.LogInformation($"Sent email to {user.Email}"); } else if (order.Status == BrokerOrderStatus.Incomming.ToString() && tx.ChainTx.Confirmations >= _walletProvider.ChainAssetSettings(order.AssetSend).MinConf) { order.Status = BrokerOrderStatus.Confirmed.ToString(); _context.BrokerOrders.Update(order); ackTxs.Add(tx); _logger.LogInformation($"Payment confirmed for order {order.Token}, {tx}"); DepositAndCreateTrade(brokerUser, order); } } } } } wallet.AcknowledgeTransactions(ackTxs); wallet.Save(); }
/// <summary> /// отдельный класс читает очередь сообщений от провайдеров /// каждый FIX-дилер получает сообщения своей группы /// </summary> public void ProcessExecutionReport(BrokerResponse response, BrokerOrder request) { Logger.InfoFormat("Запрос ({0}), ответ ({1})", request, response); requestWatchdog.OnRequestProcessed(response.RequestId); // сообщить клиенту об отказе обработать ордер // вынимаем ордер из базы MarketOrder order; int orderId; if (request.ClosingPositionID != null && request.ClosingPositionID > 0) { orderId = (int)request.ClosingPositionID; } else { orderId = request.RequestId; Logger.InfoFormat("Запрос GetMarketOrder orderId={0} requestId={1}", orderId, request.RequestId); } Logger.InfoFormat("Запрос GetMarketOrder accountId={0}, orderId={1}", request.AccountID, orderId); var res = ServerInterface.GetMarketOrder(orderId, out order); if (res == false) { errorStorage.AddMessage(new ErrorMessage(DateTime.Now, ErrorMessageType.ОтказСервера, string.Format("Дилер {0}: не найдена позиция ID={0} для обработка запроса [{1}]-[счет {2}, пара {3}]", request.RequestId, request.Id, request.AccountID, request.Instrument), null)); ServerInterface.NotifyClientOnOrderRejected(order, "не найден ордер"); return; } if (response.Status == OrderStatus.Отклонен) { var rejectReasonStr = string.IsNullOrEmpty(response.RejectReasonString) ? (response.RejectReason ?? OrderRejectReason.None).ToString() : response.RejectReasonString; ServerInterface.NotifyClientOnOrderRejected(order, rejectReasonStr); errorStorage.AddMessage(new ErrorMessage(DateTime.Now, ErrorMessageType.ОтказСервера, string.Format("Дилер {0}: отказ сервера [{1}] на запрос [{2}]-[счет {3}, пара {4}]", DealerCode, rejectReasonStr, request.Id, request.AccountID, request.Instrument), null)); return; } if (!response.Price.HasValue) { errorStorage.AddMessage(new ErrorMessage(DateTime.Now, ErrorMessageType.ОтказСервера, string.Format("Дилер {0}: отказ сервера [нет цены] на запрос [{1}]-[счет {2}, пара {3}]", DealerCode, request.Id, request.AccountID, request.Instrument), null)); ServerInterface.NotifyClientOnOrderRejected(order, "Нет цены"); return; } var deltaMarkup = request.MarkupAbs * order.Side; // закрытие позиции - ордер обработан if (request.ClosingPositionID.HasValue) { var reason = exitReasonByOrderId.ReceiveValue(order.ID); // закрыть ордер немедленно ServerInterface.CloseOrder(order.ID, response.Price.Value - (decimal)deltaMarkup, reason); return; } // открытие позы - обработано order.TimeEnter = response.ValueDate; order.PriceEnter = (float)response.Price.Value + deltaMarkup; order.State = PositionState.Opened; ServerInterface.ModifyMarketOrder(order); }
bool ChainWithdrawToCustomer(ApplicationUser brokerUser, BrokerOrder order) { var asset = order.AssetReceive; var amount = order.AmountReceive; var wallet = _walletProvider.GetChain(asset); if (wallet == null) { _logger.LogError($"No chain wallet for {asset}"); return(false); } var brokerWalletTag = wallet.GetTag(brokerUser.Id); if (brokerWalletTag == null) { _logger.LogError($"No tag for broker {brokerUser.Id}"); return(false); } var via = new ViaJsonRpc(_settings.AccessHttpUrl); var balance = via.BalanceQuery(brokerUser.Exchange.Id, asset); // validate amount var amountInt = wallet.StringToAmount(amount.ToString()); var availableInt = wallet.StringToAmount(balance.Available); if (amountInt > availableInt) { _logger.LogError("broker available balance is too small"); return(false); } if (amountInt <= 0) { _logger.LogError("amount must be greather then or equal to 0"); return(false); } var consolidatedFundsTag = _walletProvider.ConsolidatedFundsTag(); using (var dbtx = wallet.BeginDbTransaction()) { // ensure tag exists if (!wallet.HasTag(consolidatedFundsTag)) { wallet.NewTag(consolidatedFundsTag); wallet.Save(); } // register withdrawal with wallet var tag = wallet.GetTag(brokerUser.Id); if (tag == null) { tag = wallet.NewTag(brokerUser.Id); } var spend = wallet.RegisterPendingSpend(consolidatedFundsTag, consolidatedFundsTag, order.Recipient, amountInt, tag); wallet.Save(); var businessId = spend.Id; try { // link pending withdrawal to broker order var bow = new BrokerOrderChainWithdrawal { BrokerOrderId = order.Id, SpendCode = spend.SpendCode }; _context.BrokerOrderChainWithdrawals.Add(bow); // we save changes here so that we a broker order cannot be processed twice(BrokerOrderChainWithdrawal.BrokerOrderId is unique) _context.SaveChanges(); } catch { _logger.LogError($"unable to create BrokerOrderChainWithdrawal object ({order.Id}, {spend.SpendCode}"); throw; } // register withdrawal with the exchange backend var negativeAmount = -amount; try { via.BalanceUpdateQuery(brokerUser.Exchange.Id, asset, "withdraw", businessId, negativeAmount.ToString(), null); } catch (ViaJsonException ex) { _logger.LogError(ex, "Failed to update (withdraw) user balance (xch id: {0}, asset: {1}, businessId: {2}, amount {3}", brokerUser.Exchange.Id, asset, businessId, negativeAmount); if (ex.Err == ViaError.BALANCE_UPDATE__BALANCE_NOT_ENOUGH) { dbtx.Rollback(); _logger.LogError("balance not enough"); return(false); } throw; } dbtx.Commit(); } return(true); }