package org.cryptocoinpartners.bin; import java.util.Arrays; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Semaphore; import javax.inject.Inject; import org.cryptocoinpartners.enumeration.TransactionType; import org.cryptocoinpartners.module.BasicPortfolioService; import org.cryptocoinpartners.module.BasicQuoteService; import org.cryptocoinpartners.module.Context; import org.cryptocoinpartners.module.MockOrderService; import org.cryptocoinpartners.module.xchange.XchangeAccountService; import org.cryptocoinpartners.schema.DiscreteAmount; import org.cryptocoinpartners.schema.Holding; import org.cryptocoinpartners.schema.Portfolio; import org.cryptocoinpartners.schema.ReplayFactory; import org.cryptocoinpartners.schema.StrategyInstance; import org.cryptocoinpartners.schema.Transaction; import org.cryptocoinpartners.schema.TransactionFactory; import org.cryptocoinpartners.service.OrderService; import org.cryptocoinpartners.util.Replay; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.Instant; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; /** * @author Tim Olson */ @SuppressWarnings("UnusedDeclaration") @Parameters(commandNames = "backtest", commandDescription = "backtest a strategy (not functional)") public class BacktestRunMode extends RunMode { @Inject protected transient TransactionFactory transactionFactory; @Inject protected transient ReplayFactory replayFactory; @Parameter(description = "Strategy name to load", arity = 1, required = true) public List<String> strategyNames; private Context context; private static ExecutorService service; Semaphore backTestSemaphore = new Semaphore(0); // //private final Instant start = new DateTime(2015, 02, 15, 0, 0, 0, 0, DateTimeZone.UTC).toInstant(); // private final Instant start = new DateTime(2015, 8, 30, 16, 50, 0, 0, DateTimeZone.UTC).toInstant(); //private final Instant start = new DateTime(2015, 2, , 0, 0, 0, 0, DateTimeZone.UTC).toInstant(); // private final Instant end = new DateTime(2015, 11, 01, 0, 0, 0, 0, DateTimeZone.UTC).toInstant();// private final Instant start = new DateTime(2014, 01, 01, 0, 0, 0, 0, DateTimeZone.UTC).toInstant(); //private final Instant end = new DateTime(2016, 02, 20, 0, 0, 0, 0, DateTimeZone.UTC).toInstant();// //private final Instant start = new DateTime(2015, 12, 20, 0, 0, 0, 0, DateTimeZone.UTC).toInstant(); // private final Instant start = new DateTime(2015, 03, 11, 0, 0, 0, 0, DateTimeZone.UTC).toInstant(); //private final Instant end = new DateTime(2015, 03, 15, 0, 0, 0, 0, DateTimeZone.UTC).toInstant(); // private final Instant start = new DateTime(2015, 06, 19, 0, 0, 0, 0, DateTimeZone.UTC).toInstant(); // private final Instant end = new DateTime(2016, 01, 12, 0, 0, 0, 0, DateTimeZone.UTC).toInstant(); // private final Instant start = new DateTime(2015, 12, 20, 0, 0, 0, 0, DateTimeZone.UTC).toInstant(); //private final Instant start = new DateTime(2015, 12, 22, 0, 0, 0, 0, DateTimeZone.UTC).toInstant(); // private final Instant end = new DateTime(2015, 8, 31, 0, 0, 0, 0, DateTimeZone.UTC).toInstant(); //private final Instant start = new DateTime(2014, 9, 9, 23, 0, 0, 0, DateTimeZone.UTC).toInstant(); //private final Instant end = new DateTime(2014, 9, 10, 6, 0, 0, 0, DateTimeZone.UTC).toInstant(); // // private final Instant end = new DateTime(2015, 02, 27, 0, 0, 0, 0, DateTimeZone.UTC).toInstant(); // private final Instant end = new DateTime(2015, 8, 7, 0, 0, 0, 0, DateTimeZone.UTC).toInstant(); @Parameter(names = { "-p", "--position" }, arity = 2, description = "specify initial portfolio positions as {Exchange}:{Asset} {Amount} e.g. BITFINEX:BTC 1.0") // public List<String> positions = Arrays.asList("BITSTAMP:USD", "1000000"); // public List<String> positions = Arrays.asList("OKCOIN_THISWEEK:USD", "1000000"); public List<String> positions = Arrays.asList("OKCOIN_THISWEEK:USD", "40000"); @Parameter(names = { "-" }, description = "No-op switch used to end list of positions before supplying the strategy name") boolean noop = false; @Override public void run(Semaphore semaphore) { //PersistUtil.purgeTransactions(); //Replay replay = Replay.all(true); //Replay replay = Replay.between(start, end, true); Replay replay = replayFactory.between(start, end, true, backTestSemaphore); // rootInjector.createChildInjector(new PersistanceModule()); context = replay.getContext(); context.attach(XchangeAccountService.class); context.attach(BasicQuoteService.class); context.attach(BasicPortfolioService.class); context.attach(MockOrderService.class); OrderService orderService = context.getInjector().getInstance(OrderService.class); orderService.setTradingEnabled(true); for (String strategyName : strategyNames) { StrategyInstance strategyInstance = new StrategyInstance(strategyName); context.attachInstance(strategyInstance); setUpInitialPortfolio(strategyInstance); // context.getInjector().getInstance(cls) } // this should be run on seperate thread //service = Executors.newSingleThreadExecutor(); // Replay replayThread = new Replay(); //service.submit(replay); replay.run(); if (semaphore != null) semaphore.release(); //System.exit(0); // todo report P&L, etc. } private void setUpInitialPortfolio(StrategyInstance strategyInstance) { // @Inject // Portfolio portfolio; // ;= context.getInjector().getInstance(Portfolio.class); Portfolio portfolio = strategyInstance.getPortfolio(); if (positions.size() % 2 != 0) { System.err.println("You must supply an even number of arguments to the position switch. " + positions); } for (int i = 0; i < positions.size() - 1;) { Holding holding = Holding.forSymbol(positions.get(i++)); // Long str = (positions.get(i++)); DiscreteAmount amount = new DiscreteAmount(Long.parseLong(positions.get(i++)), holding.getAsset().getBasis()); DiscreteAmount price = new DiscreteAmount(0, holding.getAsset().getBasis()); Transaction initialCredit = transactionFactory.create(portfolio, holding.getExchange(), holding.getAsset(), TransactionType.CREDIT, amount, price); context.setPublishTime(initialCredit); initialCredit.persit(); context.publish(initialCredit); strategyInstance.getStrategy().init(); } } @Override public void run() { Semaphore semaphore = null; run(semaphore); } }