/// <summary> /// Place a box order. /// </summary> public void PlaceBoxOrderSell(string symbol, int shares, double lowerLimit, double upperLimit) { // we cannot place box orders when we have regular orders foreach (Order order in Orders) { if (order.Symbol == symbol && order.ActionType == ActionType.Sell) { throw new Exception("Cannot make box order for stock " + symbol); } } // do we even have this many shares? int owned = 0; foreach (Position pos in Positions) { if (pos.Symbol == symbol) { owned += pos.Shares; } } // how many sells do we already have? int ownedSells = 0; foreach (BoxOrder order in BoxOrders) { if (order.Symbol == symbol) { ownedSells += order.Shares; } } if (shares <= (owned - ownedSells)) { BoxOrders.Add(new BoxOrder(ActionType.Sell, symbol, CurrentDate, shares, lowerLimit, upperLimit)); } else { throw new Exception("Cannot place box order for " + shares + " shares of " + symbol); } }
/// <summary> /// Cancel all box orders. /// </summary> public void CancelBoxOrders() { BoxOrders.Clear(); }
/// <summary> /// Processes orders and box orders. /// </summary> private void ProcessAllOrders() { // now, what orders were placed overnight? for (int i = 0; i < Orders.Count; i++) { List <BarData> history = MarketState.FirstOrDefault(x => x.Key == Orders[i].Symbol).Value; if (Orders[i].ActionType == ActionType.Buy) { if (Orders[i].OrderType == OrderType.Limit) { double realBuyPrice = -1; // has the stocks price gone over or below the limit price today? if (history.Last().High >= Orders[i].LimitPrice && history.Last().Low <= Orders[i].LimitPrice) { realBuyPrice = Orders[i].LimitPrice; } else if (Orders[i].LimitPrice <history.Last().Open&& Orders[i].LimitPrice> history[history.Count - 2].High) { realBuyPrice = history.Last().Open; } else if (Orders[i].LimitPrice > history.Last().Open&& Orders[i].LimitPrice < history[history.Count - 2].Low) { realBuyPrice = history.Last().Open; } if (realBuyPrice != -1) { // if so, can we afford to buy this many shares? if (Orders[i].LimitPrice * Orders[i].Shares <= BuyingPower) { // buy the shares! BuyingPower -= realBuyPrice * Orders[i].Shares; // place a position Positions.Add(new Position(Orders[i].Symbol, Orders[i].Shares, realBuyPrice, CurrentDate)); // fire event Strategy.ProcessOrder(this, Orders[i], realBuyPrice); // log Log("Bought " + Orders[i].Shares + " shares of " + Orders[i].Symbol + " for $" + realBuyPrice + " per share."); // remove this order Orders.Remove(Orders[i]); } } } else if (Orders[i].OrderType == OrderType.Market) { if (history.Last().Open *Orders[i].Shares <= BuyingPower) { // buy the shares! BuyingPower -= history.Last().Open *Orders[i].Shares; // place a position Positions.Add(new Position(Orders[i].Symbol, Orders[i].Shares, history.Last().Open, CurrentDate)); // fire event Strategy.ProcessOrder(this, Orders[i], history.Last().Open); // log Log("Bought " + Orders[i].Shares + " shares of " + Orders[i].Symbol + " for $" + history.Last().Open + " per share."); // remove this order Orders.Remove(Orders[i]); } } } else if (Orders[i].ActionType == ActionType.Sell) { if (Orders[i].OrderType == OrderType.Limit) { double realSellPrice = -1; // has the stocks price gone over or below the limit price today? if (history.Last().High >= Orders[i].LimitPrice && history.Last().Low <= Orders[i].LimitPrice) { realSellPrice = Orders[i].LimitPrice; } else if (Orders[i].LimitPrice <history.Last().Open&& Orders[i].LimitPrice> history[history.Count - 2].High) { realSellPrice = history.Last().Open; } else if (Orders[i].LimitPrice > history.Last().Open&& Orders[i].LimitPrice < history[history.Count - 2].Low) { realSellPrice = history.Last().Open; } if (realSellPrice != -1) { // sell the shares! BuyingPower += realSellPrice * Orders[i].Shares; Equity += (realSellPrice - history.Last().Open) * Orders[i].Shares; int toRemove = Orders[i].Shares; List <Position> positionsToRemove = new List <Position>(); // remove the position for (int j = 0; j < Positions.Count; j++) { if (Positions[j].Symbol == Orders[i].Symbol) { if (Positions[j].BuyPrice >= realSellPrice) { Losses++; } else { Wins++; } if (Positions[j].Shares > toRemove) { Positions[j].Shares -= toRemove; break; } else if (Positions[j].Shares == toRemove) { positionsToRemove.Add(Positions[j]); break; } else if (Positions[j].Shares < toRemove) { positionsToRemove.Add(Positions[j]); toRemove -= Positions[j].Shares; } } } foreach (Position pos in positionsToRemove) { Positions.Remove(pos); } // fire event Strategy.ProcessOrder(this, Orders[i], realSellPrice); // log Log("Sold " + Orders[i].Shares + " shares of " + Orders[i].Symbol + " for $" + realSellPrice + " per share."); // remove this order Orders.Remove(Orders[i]); } } else if (Orders[i].OrderType == OrderType.Market) { // sell the shares! BuyingPower += history.Last().Open *Orders[i].Shares; int toRemove = Orders[i].Shares; List <Position> positionsToRemove = new List <Position>(); // remove the position for (int j = 0; j < Positions.Count; j++) { if (Positions[j].Symbol == Orders[i].Symbol) { if (Positions[j].BuyPrice >= history.Last().Open) { Losses++; } else { Wins++; } if (Positions[j].Shares > toRemove) { Positions[j].Shares -= toRemove; break; } else if (Positions[j].Shares == toRemove) { positionsToRemove.Add(Positions[j]); break; } else if (Positions[j].Shares < toRemove) { positionsToRemove.Add(Positions[j]); toRemove -= Positions[j].Shares; } } } foreach (Position pos in positionsToRemove) { Positions.Remove(pos); } // fire event Strategy.ProcessOrder(this, Orders[i], history.Last().Open); // log Log("Sold " + Orders[i].Shares + " shares of " + Orders[i].Symbol + " for $" + history.Last().Open + " per share."); // remove this order Orders.Remove(Orders[i]); } } } // now, what box orders were placed overnight? for (int i = 0; i < BoxOrders.Count; i++) { List <BarData> history = MarketState.FirstOrDefault(x => x.Key == BoxOrders[i].Symbol).Value; if (BoxOrders[i].ActionType == ActionType.Buy) { // todo: } else if (BoxOrders[i].ActionType == ActionType.Sell) { double realSellPrice = -1; // has the stocks price gone over or below either of the limit prices today? if (history.Last().High >= BoxOrders[i].UpperLimitPrice && history.Last().Low <= BoxOrders[i].UpperLimitPrice) { realSellPrice = BoxOrders[i].UpperLimitPrice; } else if (history.Last().High >= BoxOrders[i].LowerLimitPrice && history.Last().Low <= BoxOrders[i].LowerLimitPrice) { realSellPrice = BoxOrders[i].LowerLimitPrice; } else if (BoxOrders[i].UpperLimitPrice <history.Last().Open&& BoxOrders[i].UpperLimitPrice> history[history.Count - 2].High) { realSellPrice = history.Last().Open; } else if (BoxOrders[i].LowerLimitPrice <history.Last().Open&& BoxOrders[i].LowerLimitPrice> history[history.Count - 2].High) { realSellPrice = history.Last().Open; } else if (BoxOrders[i].UpperLimitPrice > history.Last().Open&& BoxOrders[i].UpperLimitPrice < history[history.Count - 2].Low) { realSellPrice = history.Last().Open; } else if (BoxOrders[i].LowerLimitPrice > history.Last().Open&& BoxOrders[i].LowerLimitPrice < history[history.Count - 2].Low) { realSellPrice = history.Last().Open; } if (realSellPrice != -1) { // sell the shares! BuyingPower += realSellPrice * BoxOrders[i].Shares; Equity += (realSellPrice - history.Last().Open) * BoxOrders[i].Shares; int toRemove = BoxOrders[i].Shares; List <Position> positionsToRemove = new List <Position>(); // remove the position for (int j = 0; j < Positions.Count; j++) { if (Positions[j].Symbol == BoxOrders[i].Symbol) { if (Positions[j].BuyPrice >= realSellPrice) { Losses++; } else { Wins++; } if (Positions[j].Shares > toRemove) { Positions[j].Shares -= toRemove; break; } else if (Positions[j].Shares == toRemove) { positionsToRemove.Add(Positions[j]); break; } else if (Positions[j].Shares < toRemove) { positionsToRemove.Add(Positions[j]); toRemove -= Positions[j].Shares; } } } foreach (Position pos in positionsToRemove) { Positions.Remove(pos); } // fire event Strategy.ProcessBoxOrder(this, BoxOrders[i], realSellPrice); // log Log("Sold " + BoxOrders[i].Shares + " shares of " + BoxOrders[i].Symbol + " for $" + realSellPrice + " per share."); // remove this order BoxOrders.Remove(BoxOrders[i]); } } } }