package org.cryptocoinpartners.bin; import java.io.IOException; import java.io.PrintWriter; import java.util.Arrays; import java.util.List; import java.util.concurrent.Semaphore; import java.util.regex.Matcher; import java.util.regex.Pattern; import jline.Terminal; import jline.TerminalFactory; import jline.console.ConsoleReader; import jline.console.KeyMap; import jline.console.history.MemoryHistory; import org.apache.commons.lang.StringUtils; import org.cryptocoinpartners.command.Command; import org.cryptocoinpartners.command.CommandBase; import org.cryptocoinpartners.command.ConsoleWriter; import org.cryptocoinpartners.command.ParseError; 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.module.xchange.XchangeData; import org.cryptocoinpartners.module.xchange.XchangeOrderService; import org.cryptocoinpartners.schema.DiscreteAmount; import org.cryptocoinpartners.schema.Holding; import org.cryptocoinpartners.schema.Portfolio; import org.cryptocoinpartners.schema.StrategyInstance; import org.cryptocoinpartners.schema.Transaction; import org.cryptocoinpartners.service.OrderService; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; /** * @author Tim Olson */ @SuppressWarnings("UnusedDeclaration") @Parameters(commandNames = { "console", "terminal" }, commandDescription = "run in interactive mode") public class ConsoleRunMode extends RunMode { @Parameter(names = "--live", description = "Enables LIVE trading mode (NOT RECOMMENDED)") public boolean live = false; @Override public void run(Semaphore semaphore) { try { init(); //noinspection InfiniteLoopStatement while (true) { console.println(); String line = console.readLine(); if (StringUtils.isEmpty(line)) continue; Matcher matcher = Pattern.compile("^(\\w+)\\s*(.*)$").matcher(line); if (!matcher.matches()) { out.println("Could not understand command name"); continue; } String commandName = matcher.group(1); Command command; try { command = CommandBase.commandForName(commandName, context); } catch (Throwable e) { log.warn("Could not create command " + commandName, e); internalError(); continue; } if (command == null) { out.println("Unknown command " + commandName + ". Available commands:"); out.printList(CommandBase.allCommandNames()); continue; } String argStr = matcher.group(2); if (argStr == null) argStr = ""; try { command.parse(argStr); } catch (ParseError e) { out.println(e.getMessage()); String usageHelp = command.getUsageHelp(); out.println(usageHelp == null ? commandName : usageHelp); continue; } catch (Throwable e) { log.warn("Could not parse command " + commandName, e); continue; } try { command.run(); } catch (Throwable e) { log.warn("Could not run command " + commandName, e); internalError(); continue; } history.add(line); if (semaphore != null) semaphore.release(); } } catch (IOException e) { throw new Error("Console exception", e); } } private void internalError() { out.println("Internal error: see cointrader.log"); } private void init() throws IOException { context = Context.create(); context.attach(XchangeAccountService.class); context.attach(BasicQuoteService.class); context.attach(BasicPortfolioService.class); if (live) context.attach(XchangeOrderService.class); else context.attach(MockOrderService.class); StrategyInstance strategyInstance = new StrategyInstance("ConsoleStrategy"); context.attachInstance(strategyInstance); setUpInitialPortfolio(strategyInstance); // context.publish(new TimerControlEvent(TimerControlEvent.ClockType.CLOCK_INTERNAL)); // context.publish(new TimerControlEvent(TimerControlEvent.ClockType.CLOCK_INTERNAL)); OrderService orderService = context.getInjector().getInstance(OrderService.class); context.attach(XchangeData.class); orderService.setTradingEnabled(true); Terminal terminal = TerminalFactory.get(); try { terminal.init(); } catch (Exception e) { throw new Error("Could not initialize terminal", e); } terminal.setEchoEnabled(false); console = new ConsoleReader(); String prompt = config.getString("console.cursor", "ct>") + " "; console.setPrompt(prompt); history = new MemoryHistory(); history.setMaxSize(config.getInt("console.hisory.size", 100)); console.setHistory(history); console.setHistoryEnabled(true); console.setKeyMap(KeyMap.EMACS); out = new ConsoleWriter(console); context.attach(ConsoleWriter.class, out); context.attach(PrintWriter.class, out); context.attach(ConsoleNotifications.class); console.println(); console.println("Coin Trader Console " + config.getString("project.version")); if (live) console.println("-= LIVE TRADING MODE =-"); } 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 = new Transaction(portfolio, holding.getExchange(), holding.getAsset(), TransactionType.CREDIT, amount, price); context.setPublishTime(initialCredit); initialCredit.persit(); context.publish(initialCredit); strategyInstance.getStrategy().init(); } } public List<String> positions = Arrays.asList("OKCOIN:USD", "1000000"); private Context context; private ConsoleReader console; private ConsoleWriter out; private MemoryHistory history; @Override public void run() { Semaphore semaphore = null; run(semaphore); // TODO Auto-generated method stub } }