public List<OrderDataModel> getOrders(string userID, bool top, int maxTop, int maxDefault) { //Here you can configure between two settings: top default to display //is MAX_DISPLAY_ORDERS; the upper limit is MAX_DISPLAY_TOP_ORDERS. //Set these in Web.Config/Trade.BusinessServiceHost.exe.config; and those will be the toggle //choices for the user in the Account.aspx page. try { string commandText; if (top) { commandText = string.Format(SQL_SELECT_ORDERS_BY_ID, maxTop.ToString()); } else { commandText = string.Format(SQL_SELECT_ORDERS_BY_ID, maxDefault.ToString()); } OracleParameter accountidparm = new OracleParameter(PARM_USERID, OracleDbType.Varchar2, 20); accountidparm.Value = userID; OracleDataReader rdr = OracleHelper.ExecuteReaderSingleParm(_internalConnection, _internalADOTransaction, CommandType.Text, commandText,accountidparm); List<OrderDataModel> orders = new List<OrderDataModel>(); while (rdr.Read()) { int orderid = Convert.ToInt32(rdr.GetDecimal(0)); DateTime openDate = (DateTime)rdr.GetDateTime(3); Object completionDate = null; //can be null try { if (!Convert.IsDBNull(rdr.GetDateTime(4))) completionDate = rdr.GetDateTime(4); else completionDate = DateTime.MinValue; } catch (Exception e) { string message = e.Message; completionDate = DateTime.MinValue; } OrderDataModel order = new OrderDataModel(orderid, rdr.GetString(1), rdr.GetString(2), openDate, (DateTime)completionDate, Convert.ToDouble(rdr.GetDecimal(5)), rdr.GetDecimal(6), rdr.GetDecimal(7), rdr.GetString(8)); orders.Add(order); } rdr.Close(); return orders; } catch { throw; } }
public List<OrderDataModel> getClosedOrders(string userId) { try { OracleParameter useridparm = new OracleParameter(PARM_USERID, OracleDbType.Varchar2, 20); useridparm.Value = userId; OracleDataReader rdr = OracleHelper.ExecuteReaderSingleParm(_internalConnection,_internalADOTransaction,CommandType.Text,SQL_SELECT_CLOSED_ORDERS,useridparm); List<OrderDataModel> closedorders = new List<OrderDataModel>(); DateTime completionDate = DateTime.MinValue; while (rdr.Read()) { int orderid = Convert.ToInt32(rdr.GetDecimal(0)); DateTime openDate = (DateTime)rdr.GetDateTime(4); try { completionDate = (DateTime)rdr.GetDateTime(3); } catch (Exception e) { if (e.Message.Equals("Data is Null. This method or property cannot be called on Null values.")) completionDate = DateTime.MinValue; } OrderDataModel order = new OrderDataModel(orderid, rdr.GetString(1), rdr.GetString(2), openDate, completionDate, Convert.ToDouble(rdr.GetDecimal(5)), rdr.GetDecimal(6), rdr.GetDecimal(7), rdr.GetString(8)); order.orderStatus = StockTraderUtility.ORDER_STATUS_COMPLETED; closedorders.Add(order); } if (rdr.HasRows) { rdr.Close(); useridparm = new OracleParameter(PARM_USERID, OracleDbType.Varchar2, 20); useridparm.Value = userId; OracleHelper.ExecuteNonQuerySingleParm(_internalConnection,_internalADOTransaction, CommandType.Text,SQL_UPDATE_CLOSED_ORDERS,useridparm); } else rdr.Close(); return closedorders; } catch { throw; } }
/// <summary> /// Business logic to synchrounously process the order within BSL layer, used with OrderMode="Sync." /// </summary> /// <param name="order">Order information model class with header info.</param> /// <param name="holding">Holding model class with holding to sell if applicable.</param> public void processOrderSync(OrderDataModel order, HoldingDataModel holding) { try { decimal total = 0; int holdingid = -1; QuoteDataModel quote = dalOrder.getQuoteForUpdate(order.symbol); //Get the latest trading price--this is the money going into (or out of) the users account. order.price = quote.price; //Calculate order total, and create/update the Holding. Whole holding //sells delete the holding, partials sells update the holding with new amount //(and potentially the order too), and buys create a new holding. if (order.orderType == StockTraderUtility.ORDER_TYPE_BUY) { holdingid = dalOrder.createHolding(order); total = Convert.ToDecimal(order.quantity) * order.price + order.orderFee; } else if (order.orderType == StockTraderUtility.ORDER_TYPE_SELL) { holdingid = sellHolding(order, holding); total = -1 * Convert.ToDecimal(order.quantity) * order.price + order.orderFee; } //Debit/Credit User Account. Note, if we did not want to allow unlimited margin //trading, we would change the ordering a bit and add the biz logic here to make //sure the user has enough money to actually buy the shares they asked for! //Now Update Account Balance. dalOrder.updateAccountBalance(order.accountID, total); //Update the stock trading volume and price in the quote table dalOrder.updateStockPriceVolume(order.quantity, quote); //Now perform our ACID tx test, if requested based on order type and acid stock symbols if (order.symbol.Equals(StockTraderUtility.ACID_TEST_BUY) && order.orderType == StockTraderUtility.ORDER_TYPE_BUY) throw new Exception(StockTraderUtility.EXCEPTION_MESSAGE_ACID_BUY); else if (order.symbol.Equals(StockTraderUtility.ACID_TEST_SELL) && order.orderType == StockTraderUtility.ORDER_TYPE_SELL) throw new Exception(StockTraderUtility.EXCEPTION_MESSAGE_ACID_SELL); //Finally, close the order order.orderStatus = StockTraderUtility.ORDER_STATUS_CLOSED; order.completionDate = DateTime.Now; order.holdingID = holdingid; dalOrder.closeOrder(order); //Done! return; } catch { throw; } }
/// <summary> /// Sell the holding. /// </summary> /// <param name="order"></param> /// <param name="holding"></param> /// <returns></returns> int sellHolding(OrderDataModel order, HoldingDataModel holding) { int holdingid = holding.holdingID; //There are three distinct business cases here, each needs different treatment: // a) Quantity requested is less than total shares in the holding -- update holding. // b) Quantity requested is equal to total shares in the holding -- delete holding. // c) Quantity requested is greater than total shares in the holding -- delete holding, update order table. if (order.quantity < holding.quantity) { dalOrder.updateHolding(holdingid, order.quantity); } else if (holding.quantity == order.quantity) { dalOrder.deleteHolding(holdingid); } else //We now need to back-update the order record quantity to reflect //fact not all shares originally requested were sold since the holding //had less shares in it, perhaps due to other orders //placed against that holding that completed before this one. So we will //sell the remaining shares, but need to update the final order to reflect this. if (order.quantity > holding.quantity) { dalOrder.deleteHolding(holdingid); order.quantity = holding.quantity; dalOrder.updateOrder(order); } return holdingid; }
public void updateOrder(OrderDataModel order) { try { SqlParameter[] orderparms = GetUpdateOrderParameters(); orderparms[0].Value = order.quantity; orderparms[1].Value = order.orderID; SQLHelper.ExecuteNonQuery(_internalConnection, _internalADOTransaction, CommandType.Text, SQL_UPDATE_ORDER, orderparms); } catch { throw; } return; }
public void closeOrder(OrderDataModel order) { try { SqlParameter[] closeorderparm = GetCloseOrdersParameters(); closeorderparm[0].Value = StockTraderUtility.ORDER_STATUS_CLOSED; if (order.orderType.Equals(StockTraderUtility.ORDER_TYPE_SELL)) closeorderparm[1].Value = DBNull.Value; else closeorderparm[1].Value = order.holdingID; closeorderparm[2].Value = order.price; closeorderparm[3].Value = order.orderID; SQLHelper.ExecuteNonQuery(_internalConnection, _internalADOTransaction, CommandType.Text, SQL_CLOSE_ORDER, closeorderparm); } catch { throw; } return; }
public OrderDataModel createOrder(string userID, string symbol, string orderType, double quantity, int holdingID ) { try { DateTime dt = DateTime.MinValue; int orderid = 0; OrderDataModel order = new OrderDataModel(orderid, orderType, StockTraderUtility.ORDER_STATUS_OPEN, DateTime.Now, DateTime.MinValue, quantity, (decimal)1, StockTraderUtility.getOrderFee(orderType), symbol); order.holdingID = holdingID; SqlParameter[] parm = new SqlParameter[]{new SqlParameter(PARM_USERID, SqlDbType.VarChar, 20)}; parm[0].Value = userID; order.accountID = Convert.ToInt32(SQLHelper.ExecuteScalar(_internalConnection, _internalADOTransaction, CommandType.Text, SQL_GET_ACCOUNTID, parm)); SqlParameter[] OrderParms = GetCreateOrderParameters(); OrderParms[0].Value = order.orderFee; OrderParms[1].Value = order.price; OrderParms[2].Value = order.symbol; OrderParms[3].Value = (float)order.quantity; OrderParms[4].Value = order.orderType; OrderParms[5].Value = order.accountID; OrderParms[6].Value = holdingID; order.orderID = Convert.ToInt32(SQLHelper.ExecuteScalar(_internalConnection, _internalADOTransaction, CommandType.Text, SQL_INSERT_ORDER, OrderParms)); return order; } catch { throw; } }
public int createHolding(OrderDataModel order) { try { SqlParameter orderParm = new SqlParameter(PARM_ORDERID, SqlDbType.Int, 10); orderParm.Value = order.orderID; order.accountID = Convert.ToInt32(SQLHelper.ExecuteScalarSingleParm(_internalConnection,_internalADOTransaction,CommandType.Text,SQL_GET_ACCOUNTID_ORDER,orderParm)); SqlParameter[] HoldingParms = GetCreateHoldingParameters(); HoldingParms[0].Value = order.price; HoldingParms[1].Value = (float)order.quantity; HoldingParms[2].Value = order.openDate; HoldingParms[3].Value = order.accountID; HoldingParms[4].Value = order.symbol; int holdingid = SQLHelper.ExecuteScalar(_internalConnection, _internalADOTransaction, CommandType.Text, SQL_INSERT_HOLDING, HoldingParms); return holdingid; } catch { throw; } }
/// <summary> /// Processes the order and creates holding, or sells stock. /// </summary> /// <param name="queuedOrder">Order to process.</param> private void processOrder(OrderDataModel queuedOrder) { //You could extend this application by transforming the order message //as it comes in to another format, if required. In this case, //no transformation actually takes place since the types are the same. //You can imagine different systems bridged might have different schema, //however, and transformations could be rather easily accomplished here. if (queuedOrder.orderID % Settings.DISPLAYNUMBERORDERITERATIONS == 0) { string message = string.Format("Processing Order {0}, symbol {1}, type {2}.", queuedOrder.orderID.ToString(), queuedOrder.symbol, queuedOrder.orderType); ConfigUtility.writeConsoleMessage(message + "\n",EventLogEntryType.Information,false, new Settings()); } ProcessOrder orderService = new ProcessOrder(); orderService.ProcessAndCompleteOrder(queuedOrder); return; }
int sellHolding(OrderDataModel order) { //Note, we need to make this call simply becuase holdingID is not a serialized //property on OrderDataBean; hence we cannot associate a sell order with a specific //holding without first searching for and retrieving the holding by order.OrderID. //A better approach would be to serialize the holdingID property on OrderDataModel, //then this extra query could be avoided. However, we cannot here becuase WebSphere //Trade 6.1 will not interoperate from the JSP app to .NET backend services if we do. //Of course, Trade 6.1 could easily be updated to serialize this property on OrderDataBean, //and then no "compromise" would be needed. But we want this to work with the existing IBM //Trade 6.1 code as downloadable from IBM's site. HoldingDataModel holding = dalOrder.getHoldingForUpdate(order.orderID); if (holding == null) throw new Exception(StockTraderUtility.EXCEPTION_MESSAGE_INVALID_HOLDING_NOT_FOUND); order.accountID = holding.AccountID; //There are three distinct business cases here, each needs different treatment: // a) Quantity requested is less than total shares in the holding -- update holding. // b) Quantity requested is equal to total shares in the holding -- delete holding. // c) Quantity requested is greater than total shares in the holding -- delete holding, update order table. if (order.quantity < holding.quantity) { dalOrder.updateHolding(holding.holdingID, order.quantity); } else if (holding.quantity == order.quantity) { dalOrder.deleteHolding(holding.holdingID); } else //We now need to back-update the order record quantity to reflect //fact not all shares originally requested were sold since the holding //had less shares in it, perhaps due to other orders //placed against that holding that completed before this one. So we will //sell the remaining shares, but need to update the final order to reflect this. if (order.quantity > holding.quantity) { dalOrder.deleteHolding(holding.holdingID); order.quantity = holding.quantity; order.accountID = holding.AccountID; dalOrder.updateOrder(order); } return holding.holdingID; }
/// <summary> /// SubmitOrder service operation is a service operation that processes order messages from the client /// coming in via TCP, HTTP, or a non-transacted (volatile) MSMQ WCF binding from either the BSL or another remote instance /// </summary> /// <param name="order">Order to submit.</param> public void SubmitOrder(OrderDataModel order) { System.Transactions.TransactionOptions txOps = new TransactionOptions(); txOps.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted; txOps.Timeout = TimeSpan.FromSeconds(Settings.SYSTEMDOTTRANSACTION_TIMEOUT); try { dalOrder = Trade.DALFactory.Order.Create(Settings.DAL); dalOrder.Open(Settings.TRADEDB_SQL_CONN_STRING); dalOrder.getSQLContextInfo(); } catch { } finally { dalOrder.Close(); } // Start our System.Transactions tx with the options set above. using (TransactionScope tx = new TransactionScope(TransactionScopeOption.Required, txOps)) { try { processOrder(order); //Complete transaction scope! tx.Complete(); } catch (Exception e) { string innerException = null; if (e.InnerException != null) innerException = e.InnerException.ToString(); ConfigUtility.writeErrorConsoleMessage("Error Completing Order! Exception: " + e.ToString() + "\nInner Exception: " + innerException,EventLogEntryType.Error,true, new Settings()); throw; } } return; }
public void SubmitOrderTransactedQueue(OrderDataModel order) { processOrder(order); return; }
/// <summary> /// Converts from service data contract model class to a UI Model class for quick HTML display in ASPX pages. /// </summary> private OrderDataUI convertOrderToUI(OrderDataModel order) { string completionDate; if (order != null) { //MinValue used to indicate "null" data in the DB; equates to a pending order. if (order.completionDate == DateTime.MinValue) completionDate = "Pending"; else completionDate = order.completionDate.ToString(); return new OrderDataUI(order.orderID, order.orderType, order.orderStatus, order.openDate, completionDate, order.quantity, order.price, order.orderFee, order.symbol); } else return null; }
/// <summary> /// The OPS service will use this when running in OrderProcessingBehavior="Forward". It fowards the order to a another /// remote instance of the Order Processing Service, perhaps over a different binding even, and does not actually /// process the order. This makes this instance an intermediary. /// </summary> /// <param name="order">Order to submit.</param> public void forwardOrder(OrderDataModel order) { try { SubmitOrder(order); return; } catch (Exception e) { string innerException = null; if (e.InnerException != null) innerException = e.InnerException.InnerException.ToString(); ConfigUtility.writeErrorConsoleMessage(e.ToString() + "\nInner Exception: " + innerException, EventLogEntryType.Error, true, _settingsInstance); this.Channel = null; throw; } }
/// <summary> /// Submits an order to a non-transacted queue. /// </summary> /// <param name="order"></param> public void SubmitOrder(OrderDataModel order) { try { this.Channel.SubmitOrder(order); return; } catch { this.Channel = null; throw; } }