/** * Method runStrategy. Note the current candle is just forming Enter a tier 1-3 gap in first 5min * bar direction, with a 3R target and stop @ 5min high/low. * * <p>TradeOrders create TradePositions that are associated to Contracts. TradeOrders are * associated to TradePositions and the Tradestrategy that created them. A TradePosition may have * TradeOrders from multiple Tradestrategies. * * <p>TradePositions are created when there is no open TradePosition and a TradeOrder is either * filled or partially filled. * * <p>Note TradePositions are closed when the open quantity is zero. The new TradePosition is * associated to the Contract with the 1 to 1 relationship from Contract to TradePosition. The * TradeOrder that opened the TradePosition is marked as the open order @see * org.trade.persistent.dao.TradeOrder.getIsOpenPosition() * * <p>TradePosition will have the Side set to either BOT/SLD i.e. Long/Short. If an open position * changes from Long to Short dues to an over Sell/Buy order the side will switch. * * @param candleSeries CandleSeries the series of candles that has been updated. * @param newBar boolean has a new bar just started. * @see org.trade.strategy.AbstractStrategyRule#runStrategy(CandleSeries, boolean) */ @SuppressWarnings("unused") public void runStrategy(CandleSeries candleSeries, boolean newBar) { _log.info( "Inside BreakEvenStrategy.runStrategy::" + this.getSymbol() + "_at_" + this.getCurrentCandle().getPeriod().getStart()); try { // Get the current candle CandleItem currentCandleItem = this.getCurrentCandle(); ZonedDateTime startPeriod = currentCandleItem.getPeriod().getStart(); // QuantityShares = this.getTradestrategy().getCodeValues().get(0).getCodeValue(); // QuantityShares = // this.getTradestrategy().getCodeValues().get(0).getCodeAttribute().getDefaultValue(); QuantityShares = ((Long) this.getTradestrategy().getValueCode("stockSharesQuantity")).intValue(); /* * Position is open kill this Strategy as its job is done. In this * example we would manage the position with a strategy manager. * This strategy is just used to create the order that would open * the position. */ if (this.isThereOpenPosition()) { _log.info( "Strategy complete open position filled symbol: " + getSymbol() + " startPeriod: " + startPeriod); /* * If the order is partial filled check if the risk goes beyond * 1 risk unit. If it does cancel the openPositionOrder this * will cause it to be marked as filled. */ if (OrderStatus.PARTIALFILLED.equals(this.getOpenPositionOrder().getStatus())) { if (isRiskViolated( currentCandleItem.getClose(), this.getTradestrategy().getRiskAmount(), this.getOpenPositionOrder().getQuantity(), this.getOpenPositionOrder().getAverageFilledPrice())) { this.cancelOrder(this.getOpenPositionOrder()); } } // this.cancel(); return; } else /* * Open position order was cancelled kill this Strategy as its job * is done. */ if (null != openPositionOrderKey && !this.getTradeOrder(openPositionOrderKey).isActive()) { _log.info( "Strategy complete open position cancelled symbol: " + getSymbol() + " startPeriod: " + startPeriod); updateTradestrategyStatus(TradestrategyStatus.CANCELLED); // this.cancel(); return; } else { /* * Create code here to create orders based on your conditions/rules. * * * Validamos que la estrategia solo se ejecute dentro del periodo de 9:30am a 15:00pm */ /* if (startPeriod.isAfter(this.getTradestrategy().getTradingday().getOpen().minusSeconds(1)) && startPeriod.isBefore(this.getTradestrategy().getTradingday().getClose().plusSeconds(1)) ) { // && newBar */ /* * Example On start of the second (9:35) candle check the 9:30 * candle and buy over under in the direction of the bar. * * * Validamos que no hayan transcurrido 25min (despues de la apertura) y que la estrategia * no se haya cumplido **/ if (startPeriod.isBefore(this.getTradestrategy().getTradingday().getOpen().plusMinutes(25)) && !StrategyOK) { Candle currentCandle = currentCandleItem.getCandle(); Candle prevDayCandle = getPreviousDayCandleFromDb( candleSeries, startPeriod); // Obtenemos el punto P, es decir el punto de apertura del día // anterior DecimalFormat df = new DecimalFormat("#.00"); BigDecimal currentClose = new BigDecimal(currentCandle.getClose().doubleValue()) .setScale(2, RoundingMode.HALF_EVEN); BigDecimal preDayClose = new BigDecimal(prevDayCandle.getClose().doubleValue()) .setScale(2, RoundingMode.HALF_EVEN); if (currentClose.doubleValue() == preDayClose .doubleValue()) { // Validamos que el valor actual de LOW sea igual al de P StrategyOK = Boolean.TRUE; if (!this.isThereOpenPosition()) { // Siempre que no haya una orden abierta ... // Money auxStopPrice = new Money(prevDayCandle.getLow()); Money auxStopPrice = new Money(prevDayCandle.getClose()).subtract(new Money(0.04)); Money limitPrice = new Money(prevDayCandle.getClose()); LastAuxStopPrice = auxStopPrice.doubleValue(); TradeOrder tradeOrder = this.createOrder( this.getTradestrategy().getContract(), Action.BUY, OrderType.STPLMT, limitPrice, auxStopPrice, QuantityShares, false, true); // Creamos y transmitimos una orden BUY, STPLMT = LOW - 4c } _log.info( "StrategyOK::" + StrategyOK + ", LastAuxStopPrice::" + LastAuxStopPrice + ", Symbol::" + this.getSymbol()); /* TradeOrder tradeOrder = new TradeOrder(this.getTradestrategy(), Action.BUY, OrderType.STPLMT, 100, price, price.add(new BigDecimal(0.02)), TradingCalendar.getDateTimeNowMarketTimeZone()); //tradeOrder.setClientId(clientId); tradeOrder.setTransmit(new Boolean(true)); //tradeOrder.setStatus(OrderStatus.UNSUBMIT); this.submitOrder(this.getTradestrategy().getContract(), tradeOrder); */ } } else if (startPeriod.isAfter( this.getTradestrategy().getTradingday().getOpen().plusMinutes(25)) && !StrategyOK) { // Si han pasado 25min y no se cumplio la estrategia, cancelamos la // ejecución // this.cancel(); return; } else if (StrategyOK) { // Si se ejecuto la estrategia... // Candle prevDayCandle = getPreviousDayCandleFromDb(candleSeries, startPeriod); /* * Is the candle in the direction of the Tradestrategy side i.e. * a long play should have a green 5min candle */ CandleItem prevCandleItem = null; if (getCurrentCandleCount() > 0) { prevCandleItem = (CandleItem) candleSeries.getDataItem(getCurrentCandleCount() - 1); // AbstractStrategyRule // .logCandle(this, prevCandleItem.getCandle()); } this.reFreshPositionOrders(); // double lastAuxStopPrice = this.getOpenPositionOrder().getAuxPrice().doubleValue(); if (currentCandleItem.getClose() > prevCandleItem.getClose() && currentCandleItem.getClose() >= addAPercentToANumber(LastAuxStopPrice, 50)) { /* * Validamos que haya un incremento en LOW entre la * posicion actual y la posicion anterior del dia; y * además, que el incremento de LOW del dia sea mayor o * igual a un 50% de LOW del dia anterior */ /* Money stopPrice = addPennyAndRoundStop(this .getOpenPositionOrder().getAverageFilledPrice() .doubleValue(), getOpenTradePosition() .getSide(), Action.BUY, 0.04); moveStopOCAPrice(stopPrice, true); */ Money auxStopPrice = new Money(addAPercentToANumber(LastAuxStopPrice, 50)).subtract(new Money(0.04)); Money limitPrice = new Money(addAPercentToANumber(LastAuxStopPrice, 50)); LastAuxStopPrice = auxStopPrice.doubleValue(); TradeOrder tradeOrder = this.updateOrder( this.getOpenPositionOrder().getOrderKey(), Action.BUY, OrderType.STPLMT, limitPrice, auxStopPrice, QuantityShares, false, true); // Creamos y transmitimos una orden BUY, STPLMT = (LOW + 50%) - 4c this.reFreshPositionOrders(); } _log.info( "StrategyOK::" + StrategyOK + ", LastAuxStopPrice::" + LastAuxStopPrice + ", Symbol::" + this.getSymbol()); } } /* * Close any opened positions with a market order at day end minus * one bar. * if (!currentCandleItem.getLastUpdateDate().isBefore( this.getTradestrategy() .getTradingday() .getClose() .minusMinutes( this.getTradestrategy().getBarSize() / 60))) { cancelOrdersClosePosition(true); _log.info("Rule 15:55:00 close all open positions: " + getSymbol() + " Time: " + startPeriod); this.cancel(); } */ } catch (StrategyRuleException | PersistentModelException | ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException | IOException ex) { _log.error("Error runRule exception: " + ex.getMessage(), ex); error(1, 10, "Error runRule exception: " + ex.getMessage()); } catch (Exception ex) { _log.error("Error runRule exception: " + ex.getMessage(), ex); error(1, 10, "Error runRule exception: " + ex.getMessage()); } }
/** * Method runStrategy. Note the current candle is just forming Enter a tier 1-3 gap in first 5min * bar direction, with a 3R target and stop @ 5min high/low. * * <p>TradeOrders create TradePositions that are associated to Contracts. TradeOrders are * associated to TradePositions and the Tradestrategy that created them. A TradePosition may have * TradeOrders from multiple Tradestrategies. * * <p>TradePositions are created when there is no open TradePosition and a TradeOrder is either * filled or partially filled. * * <p>Note TradePositions are closed when the open quantity is zero. The new TradePosition is * associated to the Contract with the 1 to 1 relationship from Contract to TradePosition. The * TradeOrder that opened the TradePosition is marked as the open order @see * org.trade.persistent.dao.TradeOrder.getIsOpenPosition() * * <p>TradePosition will have the Side set to either BOT/SLD i.e. Long/Short. If an open position * changes from Long to Short dues to an over Sell/Buy order the side will switch. * * @param candleSeries CandleSeries the series of candles that has been updated. * @param newBar boolean has a new bar just started. * @see org.trade.strategy.AbstractStrategyRule#runStrategy(CandleSeries, boolean) */ public void runStrategy(CandleSeries candleSeries, boolean newBar) { try { // Get the current candle CandleItem currentCandleItem = this.getCurrentCandle(); ZonedDateTime startPeriod = currentCandleItem.getPeriod().getStart(); /* * Position is open kill this Strategy as its job is done. In this * example we would manage the position with a strategy manager. * This strategy is just used to create the order that would open * the position. */ if (this.isThereOpenPosition()) { _log.info( "La posicion esta abierta para el symbol: " + getSymbol() + " startPeriod: " + startPeriod); /* * If the order is partial filled check if the risk goes beyond * 1 risk unit. If it does cancel the openPositionOrder this * will cause it to be marked as filled. */ if (OrderStatus.PARTIALFILLED.equals(this.getOpenPositionOrder().getStatus())) { if (isRiskViolated( currentCandleItem.getClose(), this.getTradestrategy().getRiskAmount(), this.getOpenPositionOrder().getQuantity(), this.getOpenPositionOrder().getAverageFilledPrice())) { this.cancelOrder(this.getOpenPositionOrder()); } } this.cancel(); return; } else { try { CandlePivote pivote = stocksPivoting.get(getSymbol()); if (pivote == null) { _log.info("PRIMER ACCESO>>>>"); stocksPivoting.put(getSymbol(), new CandlePivote(currentCandleItem)); _log.info(" * ******************************************** *"); return; } CandleItem pivoteCandle = pivote.getPivote(); _log.info(" * PIVOTE *"); _log.info(pivoteCandle.getCandle().getContract() + " : " + pivoteCandle.getPeriod()); _log.info("LOW: " + pivoteCandle.getLow()); _log.info("HIGH: " + pivoteCandle.getHigh()); _log.info("CLOSE: " + pivoteCandle.getClose()); _log.info(" * CURRENT *"); _log.info(getSymbol() + " : " + currentCandleItem.getPeriod()); _log.info("LOW: " + currentCandleItem.getLow()); _log.info("HIGH: " + currentCandleItem.getHigh()); _log.info("CLOSE: " + currentCandleItem.getClose()); _log.info(" ** DATA ** "); long diff = currentCandleItem.getPeriod().getFirstMillisecond() - pivoteCandle.getPeriod().getFirstMillisecond(); long diffMinutes = diff / (60 * 1000) % 60; // double diffLows = Math.abs(currentCandleItem.getLow() - pivoteCandle.getLow()); // double diffHighs = Math.abs(currentCandleItem.getHigh() - pivoteCandle.getHigh()); double rangoInferior = pivoteCandle.getClose() - 0.05; double rangoSuperior = pivoteCandle.getClose() + 0.15; // _log.info(getSymbol() + " :: Diff Low: "+ diffLows ); // _log.info(getSymbol() + " :: Diff High: "+ diffHighs ); // _log.info(getSymbol() + " :: Diff Close: "+ diffClose ); _log.info(getSymbol() + " :: Rango Inferior: " + rangoInferior); _log.info(getSymbol() + " :: Rango Superior: " + rangoSuperior); _log.info(getSymbol() + " :: TimeElapsed: " + diffMinutes + " min. "); if (pivote.isCandidato()) { if (currentCandleItem.getClose() > rangoInferior && currentCandleItem.getClose() < rangoSuperior) { // Esta dentro del rango de valores deseados, checamos el tiempo que ha pasado // 180 minutos = 3 hrs _log.info(getSymbol() + " sigue siendo candidato"); if (diffMinutes > 180) { // Si el tiempo es mayor a 3 horas, eliminamos el monitoreo _log.info(getSymbol() + " ya sobrepaso las 3 hrs"); pivote.setCandidato(false); stocksPivoting.put(getSymbol(), pivote); } } else { // Salio fuera del rango, verificamos si hacemos un buy o un sell _log.info(getSymbol() + " es candidato y salio fuera del rango"); double rangoInferiorSell = pivoteCandle.getClose() - 0.20; double rangoSuperiorBuy = pivoteCandle.getClose() + 0.20; if (currentCandleItem.getClose() < rangoInferiorSell) { // El stock sobrepaso los 20 centavos a la baja _log.info(getSymbol() + " sobrepaso 20 centavos a la baja. SELL"); Money limitPrice = new Money(currentCandleItem.getLow()); Money auxStopPrice = new Money(currentCandleItem.getLow()).add(new Money(0.10)); _log.info(getSymbol() + " LIMIT PRICE " + limitPrice); _log.info(getSymbol() + " STOP PRICE " + auxStopPrice); int cantidadCompra = ((Long) this.getTradestrategy().getValueCode("stockSharesQuantity")).intValue(); TradeOrder tradeOrder = this.createOrder( this.getTradestrategy().getContract(), Action.SELL, OrderType.STPLMT, limitPrice, auxStopPrice, cantidadCompra, false, true); // Creamos y transmitimos una orden BUY, STPLMT = LOW - 4c this.reFreshPositionOrders(); _log.info(" * ******************************************** *"); return; } if (currentCandleItem.getClose() > rangoSuperiorBuy) { _log.info(getSymbol() + " sobrepaso 20 centavos hacia arriba. COMPRAR"); Money limitPrice = new Money(currentCandleItem.getHigh()); Money auxStopPrice = new Money(currentCandleItem.getHigh()).subtract(new Money(0.10)); _log.info(getSymbol() + " LIMIT PRICE " + limitPrice); _log.info(getSymbol() + " STOP PRICE " + auxStopPrice); int cantidadCompra = ((Long) this.getTradestrategy().getValueCode("stockSharesQuantity")).intValue(); TradeOrder tradeOrder = this.createOrder( this.getTradestrategy().getContract(), Action.BUY, OrderType.STPLMT, limitPrice, auxStopPrice, cantidadCompra, false, true); // Creamos y transmitimos una orden BUY, STPLMT = LOW - 4c this.reFreshPositionOrders(); _log.info(" * ******************************************** *"); return; } } System.out.println(" * ******************************************** *"); return; } if (currentCandleItem.getClose() > rangoInferior && currentCandleItem.getClose() < rangoSuperior) { // Esta en el rango de valores deseados if (diffMinutes > 20) { // Ya han pasado mas de 20 minutos y el valor se sigue conservando // Definimos al pivote como candidato para ser comprado o vendido pivote.setCandidato(true); stocksPivoting.put(getSymbol(), pivote); } else { // Conservamos el pivote, aun no se llega al tiempo limite _log.info("CONSERVANDO PIVOTE, SIGUE EN OBSERVACION "); pivote.setCandidato(false); stocksPivoting.put(getSymbol(), pivote); } } else { // Esta fuera del rango de valores deseados, cambiamos el pivote al currentCandle _log.info("CAMBIANDO PIVOTE"); pivote.setPivote(currentCandleItem); pivote.setCandidato(false); stocksPivoting.put(getSymbol(), pivote); } _log.info(" * ******************************************** *"); } catch (Exception ex) { _log.error("Error runRule exception: " + ex.getMessage(), ex); error(1, 10, "Error runRule exception: " + ex.getMessage()); } } /* * Create code here to create orders based on your conditions/rules. */ // getCandle(startPeriod) // // if (startPeriod.equals(this.getTradestrategy().getTradingday() // .getOpen() // .plusMinutes(this.getTradestrategy().getBarSize() / 60)) // && newBar) { // // /* // * Example On start of the second (9:35) candle check the 9:30 // * candle and buy over under in the direction of the bar. // */ // // // } /* * Close any opened positions with a market order at day end minus * one bar. if (!currentCandleItem.getLastUpdateDate().isBefore( this.getTradestrategy() .getTradingday() .getClose() .minusMinutes( this.getTradestrategy().getBarSize() / 60))) { cancelOrdersClosePosition(true); _log.info("Rule 15:55:00 close all open positions: " + getSymbol() + " Time: " + startPeriod); this.cancel(); } */ } catch (StrategyRuleException ex) { _log.error("Error runRule exception: " + ex.getMessage(), ex); error(1, 10, "Error runRule exception: " + ex.getMessage()); } }