public override void OnBar(Bar bar) { // good practice to check if a series has the date you are interested in before you try // to use it if (b.Contains(bar)) { // if we don't have a position and prices are below the lower band, open a long position if (!HasPosition) { if (b[bar.DateTime] * 100 <= BLevel) { buyOrder = BuyOrder(Qty, "Entry"); buyOrder.Send(); } } else { barsFromEntry++; // if we _have_ reached the exit day (4 days after entry), cancel the profit target // sell order, and issue a new market order to close the position now. if (barsFromEntry == MaxDuration) { barsFromEntry = 0; // cancel existing sell order if there is one if (sellOrder != null) sellOrder.Cancel(); Sell(Qty, "Exit (Max Duration)"); } } } }
public override void OnBar(Bar bar) { // always a good practice to be sure a series contains // a bar for a particular date before you try to use it if (bbl.Contains(bar.DateTime)) { // We are always trying to buy at the lower Bollinger // limit, and sell when the price goes up to the // latest SMA value. So we are constantly // updating both the buy point and the sell point. // if we don't have an open position in this instrument, // update the buy point to the latest lower bbl limit if (!HasPosition) { if (buyOrder != null) buyOrder.Cancel(); buyOrder = BuyLimitOrder(Qty, bbl.Last, "Entry"); buyOrder.Send(); } // else if we already have a position going, update // the sell point to follow the latest SMA value else UpdateExitLimit(); } }
public override void OnBar(Bar bar) { if (bbl.Contains(bar.DateTime)) { if (!HasPosition) { // cancel previos buy limit if (buyLimit != null) buyLimit.Cancel(); // calculate limit price double buyPrice = bbl.Last * (1 - Percent / 100); // place new limit orders buyLimit = BuyLimitOrder(Qty, buyPrice, "Entry"); buyLimit.Send(); } else { barsFromEntry++; // close position at the second bar after entry if (barsFromEntry == 2) { barsFromEntry = 0; sellLimit.Cancel(); Sell(Qty, "Exit (Second Bar After Entry)"); } } } }
public override void OnBar(Bar bar) { // if we don't have a position and we have some bars // in the bollinger series, try to enter a new trade if (!HasPosition) { if (bbl.Count > 0) { // if the current bar is below the lower bollinger band // buy long to close the gap if (Bars.Crosses(bbl, bar) == Cross.Below) { buyOrder = MarketOrder(OrderSide.Buy, Qty, "Entry"); buyOrder.Send(); } } } else { // else if we DO have an existing position, and if // today's bar is above our entry price (profitable), // then close the position with a market order if (entryPrice < bar.Close) { barsFromEntry = 0; Sell(Qty, "Exit (Take Profit)"); } else barsFromEntry++; } }
public override void OnBarOpen(Bar bar) { // we need to let the first bar go by before we can // calculate the breakout limit if (prevClose != -1) { // if we do not have a position, then cancel the // previous limit order (it is out of date) if (!HasPosition) { if (buyOrder != null) buyOrder.Cancel(); // now try to enter a trade by setting a limit order // to automatically buy in if the big 4% jump arrives. // This order will reside on the exchange servers, and // will execute during the day if the limit is triggered. double breakout_fraction = 1 + (BreakoutPercent / 100); double breakout_price = prevClose * breakout_fraction; buyOrder = BuyStopOrder(Qty, breakout_price, "Entry"); buyOrder.Send(); } // if we have a position open, then close it now. // Now (which is the leading edge of today's daily bar) // is the start of the day after the trade was opened. else Sell(Qty, "Exit"); } }
public override void OnPositionOpened() { // when we open a position, immediately issue a limit order // for our 1% profit target double target_price = sellOrder.AvgPrice * (1 - ProfitTarget / 100); buyOrder = BuyLimitOrder(Qty, target_price, "Exit (Take Profit)"); buyOrder.Send(); }
private void UpdateExitLimit() { // cancel old exit point order, if it exists if (sellOrder != null) sellOrder.Cancel(); // Issue a new order with the latest SMA value. This is // kind of a "trailing SMA sell order" that follows the SMA. sellOrder = SellLimitOrder(Qty, sma.Last, "Exit"); sellOrder.Send(); }
/// <summary> /// /// </summary> /// <param name="bar"></param> public virtual void HandleBarOpen(Bar bar) { if (bar.BeginTime >= triggerTime) { if (openPrice == null) { openPrice = bar.Open; } if (!HasPosition && closingOrder == null) { OrderSide? side = null; double targetPrice = openPrice.Value; double targetQuantity = 0; if (longPositionQuantity.HasValue && longPositionQuantity.Value > 0) { side = OrderSide.Sell; targetPrice = GetSlippageAdjustedPrice(openPrice.Value, side.Value); targetQuantity = longPositionQuantity.Value; } if (shortPositionQuantity.HasValue && shortPositionQuantity.Value > 0) { side = OrderSide.Buy; targetPrice = GetSlippageAdjustedPrice(openPrice.Value, side.Value); targetQuantity = shortPositionQuantity.Value; } targetPrice = RoundPrice(targetPrice); if (side.HasValue) { closingOrder = LimitOrder(side.Value, targetQuantity, targetPrice, "Auto closing order"); LogOrder("Closing", Instrument.Symbol, side.Value, targetQuantity, targetPrice); if (AutoSubmit) closingOrder.Send(); } } } }
public override void OnBar(Bar bar) { if (entryEnabled) { if (Bars.Count > Length) if (bar.High > highestHigh) { Buy(Qty, "Entry"); if (OCAExitEnabled) { limitOrder = SellLimitOrder(Qty, LimitOCALevel * bar.Close, "Limit OCA " + OCACount); limitOrder.OCAGroup = "OCA " + Instrument.Symbol + " " + OCACount; stopOrder = SellStopOrder(Qty, StopOCALevel * bar.Close, "Stop OCA " + OCACount); stopOrder.OCAGroup = "OCA " + Instrument.Symbol + " " + OCACount; limitOrder.Send(); stopOrder .Send(); OCACount++; } entryEnabled = false; barCount = 0; } } else { barCount++; if (TimeExitEnabled && barCount > BarsToExit) { Sell(Qty, "Time Exit"); entryEnabled = true; } } if (Bars.Count >= Length) highestHigh = Bars.HighestHigh(Length); }
public override void OnBar(Bar bar) { // we need to let a bar go by to capture the prev close if (prevClose != -1) { // if we don't have a position open, update the count // of up days, and try to enter a trade if (!HasPosition) { if (prevClose < bar.Close) count++; else count = 0; // if we have seen 4 (consClosesCount is equal to 4 by default) up days, AND if the last day // up was 2% or more, then open a new position, // going short on the day's close if (count == ConsClosesCount) { if ((bar.Close - prevClose) / prevClose >= UpPercent / 100) { sellOrder = MarketOrder(OrderSide.Sell, Qty, "Entry"); sellOrder.Send(); } } } // if we have a position open, cancel our previous // 1% profit target order, and close using a market order else { buyOrder.Cancel(); Buy(Qty, "Buy Cover"); } } // now today's close becomes the previous close prevClose = bar.Close; }
public override void OnBar(Bar bar) { // if we do not have a position, update the limit buy order to be 5% above today's close if (!HasPosition) { // cancel the old limit order (it's out of date now) if (buyOrder != null) buyOrder.Cancel(); // issue a new buy order at 5% below today's close this order will execute tomorrow // if price is matched double buy_price = bar.Close * (1 - (Percent / 100)); buyOrder = BuyLimitOrder(Qty, buy_price, "Entry"); buyOrder.Send(); } // else we opened a position today using our limit order from yesterday, so now close // the position at the end of today. We expect that such a big drop was freaky, and that // prices recovered during the day. If not, this order stops further losses. else Sell(Qty, "Exit"); }
public override void OnPositionOpened() { sellOrder = SellLimitOrder(Qty, prevClose, "Limit Exit"); sellOrder.Send(); }
public override void OnBar(Bar bar) { // does the fast average cross over the slow average? // if so, time to buy long Cross cross = sma1.Crosses(sma2, bar); // we only allow one active position at a time if (entryEnabled) { // if price trend is moving upward, open a long // position using a market order, and send it in if (cross == Cross.Above) { marketOrder = MarketOrder(OrderSide.Buy, Qty, "Entry"); marketOrder.Send(); // if one cancels all exit method is desired, we // also issue a limit (profit target) order, and // a stop loss order in case the breakout fails. // The OCA exit method uses a real stop loss order. // The Stop exit method uses a stop indicator. // Use either the OCA or Stop method, not both at once. if (OCAExitEnabled) { // create and send a profit limit order double profitTarget = LimitOCALevel * bar.Close; limitOrder = SellLimitOrder(Qty, profitTarget, "Limit OCA " + OCACount); limitOrder.OCAGroup = "OCA " + Instrument.Symbol + " " + OCACount; limitOrder.Send(); // create and send a stop loss order double lossTarget = StopOCALevel * bar.Close; stopOrder = SellStopOrder(Qty, lossTarget, "Stop OCA " + OCACount); stopOrder.OCAGroup = "OCA " + Instrument.Symbol + " " + OCACount; stopOrder.Send(); // bump the OCA count to make OCA group strings unique OCACount++; } entryEnabled = false; } } // else if entry is disabled on this bar, we have an open position else { // if we are using the crossover exit, and if the fast // average just crossed below the slow average, issue a // market order to close the existing position if (CrossoverExitEnabled) if (cross == Cross.Below) { marketOrder = MarketOrder(OrderSide.Sell, Qty, "Crossover Exit"); marketOrder.Send(); } } }
public override void OnStopExecuted(Stop stop) { // if our trailing stop indicator was executed, // issue a market sell order to close the position. marketOrder = MarketOrder(OrderSide.Sell, Qty, "Stop Exit"); marketOrder.Send(); }
private void PlaceSellLimit() { // calculate price that satisfies the profit target double sellPrice = buyLimit.AvgPrice * (1 + ProfitTarget / 100); sellLimit = SellLimitOrder(Qty, sellPrice, "Exit (Profit Target)"); sellLimit.Send(); }
private void ReversePosition() { // reverse the position with a market order // Use double the position size to flip the position if (Position.Side == PositionSide.Long) { sellOrder = MarketOrder(OrderSide.Sell, Qty * 2, "Reverse the Position"); sellOrder.Send(); } else { buyOrder = MarketOrder(OrderSide.Buy, Qty * 2, "Reverse the Position"); buyOrder.Send(); } }
private void ExecuteClosingOrder(long size) { if (OpenQuantity > 0 && closingOrderQueued) { OrderSide orderSide = OrderSide.Sell; double targetQuantity = 0; double targetPrice = 0; PriceCalculator priceCalc = new PriceCalculator(LoggingConfig); QuantityCalculator qtyCalc = new QuantityCalculator(LoggingConfig); targetPrice = priceCalc.Calculate( new PriceCalculatorInput() { CurrentBar = closingInstrument.Bar, PreviousBar = GetPreviousBar(closingInstrument, closingInstrument.Bar, PeriodConstants.PERIOD_MINUTE), Atr = GetAtrValue(Instrument, AtrPeriod, triggerTime.Value), AllowedSlippage = AllowedSlippage, FavorableGap = FavorableGap, FavorableGapAllowedSlippage = FavorableGapAllowedSlippage, UnfavorableGap = UnfavorableGap, UnfavorableGapAllowedSlippage = UnfavorableGapAllowedSlippage, OrderSide = orderSide }); targetQuantity = qtyCalc.CalculatePositionSizedQuantity(OpenQuantity, new QuantityCalculatorInput() { PositionSizePercentage = PositionSizePercentage, RoundLots = RoundLots }); targetPrice = priceCalc.RoundPrice(targetPrice, closingInstrument); if (targetPrice <= 0 || targetQuantity <= 0) throw new ApplicationException( string.Format("Invalid price of quantity calculated. Price {0:c}, Qty {1}", targetPrice, targetQuantity)); string orderName = GetAutoPlacedOrderName(orderSide, "FlipFlop-Closed", closingInstrument.Symbol); closingOrder = CreateOrder(orderSide, targetQuantity, orderName, targetPrice); LoggingUtility.LogOrder(LoggingConfig, orderName, orderSide, targetQuantity, targetPrice, retryCount); if (AutoSubmit) closingOrder.Send(); if (!AmountIncludesOpenPosition) { double proceeds = (targetPrice * targetQuantity); PortfolioAmount = PortfolioAmount + proceeds; LoggingUtility.WriteInfo(LoggingConfig, string.Format( "The sale of {0} for {1:c} have been added to portfolio. New total = {2:c} ", closingInstrument.Symbol, proceeds, PortfolioAmount)); } } }
public override void OnPositionOpened() { // when a position is opened, calculate profit target exitPrice = buyOrder.AvgPrice * (1 + ProfitPercent / 100); // cancel existing sell order if there is one if (sellOrder != null) sellOrder.Cancel(); // issue a new sell limit order at the profit target price sellOrder = SellLimitOrder(Qty, exitPrice, "Exit (Profit Target)"); sellOrder.Send(); }