package org.cryptocoinpartners.module; import javax.annotation.Nullable; import org.cryptocoinpartners.schema.BaseStrategy; import org.cryptocoinpartners.schema.Fill; import org.cryptocoinpartners.schema.Order; import org.cryptocoinpartners.schema.OrderBuilder; /** * This enhances the BaseStrategy by providing a simple state machine which tracks whether the Strategy is warming up, * ready to trade, in a trade, panicking, or stopped. * * @author Tim Olson */ @SuppressWarnings("UnusedDeclaration") public abstract class SimpleStatefulStrategy extends BaseStrategy { /** You must call this method when the Strategy has collected enough data to begin trading */ protected void ready() { if (state == State.WARMUP) state = State.READY; } /** Override this method to build the Order to use when entering a trade. If you return null, then the trade * entry will be aborted and you will stay out of the trade */ @Nullable protected abstract OrderBuilder.CommonOrderBuilder buildEntryOrder(); @Nullable protected abstract OrderBuilder.CommonOrderBuilder buildStopOrder(Fill fill); /** Override this method to build the Order to use when exiting a trade. If you return null, the trade exit * will be aborted and you will stay in the trade */ @Nullable protected abstract OrderBuilder.CommonOrderBuilder buildExitOrder(Order entryOrder); /** * You must call this method when your Strategy wants to enter a trade. If the strategy is not ready to trade, * nothing will happen */ protected void enterTrade() { if (state == State.READY) { OrderBuilder.CommonOrderBuilder orderBuilder = buildEntryOrder(); if (orderBuilder != null) { entryOrder = orderBuilder.getOrder(); //entryOrder. state = State.ENTERING; log.info("Entering trade with order " + entryOrder); try { orderService.placeOrder(entryOrder); } catch (Throwable e) { log.info("Unable to place order " + entryOrder); } } } } /** * You must call this method when your Strategy wants to exit a trade. If the strategy is not currently in * a trade, nothing will happen */ protected void exitTrade() { if (state == State.INVESTED) { OrderBuilder.CommonOrderBuilder orderBuilder = buildExitOrder(entryOrder); if (orderBuilder != null) { exitOrder = orderBuilder.getOrder(); state = State.EXITING; log.debug("Exiting trade with order " + exitOrder); try { orderService.placeOrder(exitOrder); } catch (Throwable e) { // TODO Auto-generated catch block log.info("Unable to place order " + exitOrder); } } } } protected void stopTrade(Fill fill) { OrderBuilder.CommonOrderBuilder orderBuilder = buildStopOrder(fill); //if (orderBuilder != null) { // stopOrder = orderBuilder.getOrder(); // if (state == State.INVESTED) // state = State.DIVESTING; // else if (state == State.DIVESTING) // state = State.INVESTING; // log.debug("Exiting trade with order " + stopOrder); //orderService.placeOrder(stopOrder); //} } // todo listen for panic notifications protected void panic() { state = State.PANICKING; // todo create panic order } protected void stop() { state = State.STOP; } protected void setInterval(double interval) { this.interval = interval; } protected void setTrendInterval(double trendInterval) { this.trendInterval = trendInterval; } protected void setRunsInterval(double runsInterval) { this.runsInterval = runsInterval; } protected enum State { /** the Strategy has started but does not have enough data to begin trading */ WARMUP, READY, ENTERING, INVESTED, EXITING, PANICKING, STOP, LONG, SHORT } private Order entryOrder; private Order exitOrder; private Order stopOrder; protected State state = State.WARMUP; //defualt 24Hr bars protected static double interval = 86400; protected static double runsInterval = 86400; protected static double trendInterval = 86400; }