/// <summary> /// Estimate number of shares, given a kind of operation. /// </summary> /// <param name="symbol">The symbol to operate.</param> /// <param name="order">The kind of order.</param> /// <returns>The signed number of shares given the operation.</returns> public decimal PositionShares(Symbol symbol, BaseStrategy strategy) { decimal quantity = 0; int operationQuantity; decimal targetSize = GetBetSize(symbol, strategy); if (targetSize <= 10) { targetSize = 0; strategy.ActualSignal = OrderSignal.doNothing; } switch (strategy.ActualSignal) { case OrderSignal.goLongLimit: case OrderSignal.goLong: //operationQuantity = CalculateOrderQuantity(symbol, targetSize); // let the algo decide on order quantity //operationQuantity = (int)targetSize; quantity = Math.Min(maxOperationQuantity, targetSize); break; case OrderSignal.goShortLimit: case OrderSignal.goShort: //operationQuantity = CalculateOrderQuantity(symbol, targetSize); // let the algo decide on order quantity operationQuantity = (int)targetSize; quantity = -Math.Min(maxOperationQuantity, targetSize); break; case OrderSignal.closeLong: case OrderSignal.closeShort: if (Portfolio[symbol].Quantity != 0) quantity = -Portfolio[symbol].Quantity; break; case OrderSignal.revertToLong: case OrderSignal.revertToShort: if (Portfolio[symbol].Quantity != 0) quantity = -2 * Portfolio[symbol].Quantity; break; default: quantity = 0; break; } return quantity; }
/// <summary> /// Executes the ITrend strategy orders. /// </summary> /// <param name="symbol">The symbol to be traded.</param> /// <param name="strategy">The actual arder to be execute.</param> /// <param name="data">The actual TradeBar data.</param> private void ExecuteStrategy(Symbol symbol, BaseStrategy strategy, KeyValuePair<Symbol, TradeBar> data) { decimal limitPrice = 0m; int shares = Convert.ToInt32(PositionShares(symbol, strategy)); if (shares == 0) { return; } ILimitPriceCalculator priceCalculator = new InstantTrendLimitPriceCalculator(); OrderTicket ticket; if (shares == 0) strategy.ActualSignal = OrderSignal.doNothing; switch (strategy.ActualSignal) { case OrderSignal.goLongLimit: // Define the limit price. limitPrice = priceCalculator.Calculate(data.Value, strategy.ActualSignal, RngFac); //ticket = MarketOrder(symbol, shares, false, strategy.Id.ToString(CultureInfo.InvariantCulture)); ticket = LimitOrder(symbol, shares, limitPrice); break; case OrderSignal.goShortLimit: limitPrice = priceCalculator.Calculate(data.Value, strategy.ActualSignal, RngFac); //ticket = MarketOrder(symbol, shares, false); ticket = LimitOrder(symbol, shares, limitPrice); break; case OrderSignal.goLong: case OrderSignal.goShort: case OrderSignal.closeLong: case OrderSignal.closeShort: case OrderSignal.revertToLong: case OrderSignal.revertToShort: ticket = MarketOrder(symbol, shares); //_ticketsQueue.Add(ticket); break; default: break; } }
private decimal GetBetSize(Symbol symbol, BaseStrategy strategy) { decimal currentPrice = Portfolio[symbol].Price; decimal betsize = Portfolio[symbol].Invested ? Math.Abs(Portfolio[symbol].Quantity) : Math.Abs((15m / 26m) * Portfolio.Cash / currentPrice); if (betsize <= 10) { betsize = 0; strategy.ActualSignal = OrderSignal.doNothing; } return betsize; }
/// <summary> /// Handles the case where an order is partially filled. /// </summary> /// <param name="data">The current data</param> /// <param name="strategy"></param> private void HandlePartiallyFilled(KeyValuePair<Symbol, TradeBar> data, BaseStrategy strategy) { IEnumerable<OrderTicket> livetickets = Transactions.GetOrderTickets( t => t.Symbol == data.Key && (t.Status == OrderStatus.Submitted || t.Status == OrderStatus.PartiallyFilled)); if (livetickets != null) { foreach (OrderTicket liveticket in livetickets) { if (strategy.TradeAttempts++ > 3) { liveticket.Cancel(); //Log(string.Format("Order {0} cancellation sent. Trade attempts > 3.", liveticket.OrderId)); } } } }