concept Chaser extends G22TradingStrategy { // Juicer parameters settable double maxLoss = 0.6; settable double pullback = 0.4; // internal persistable srecord Juicer(double maxLoss, double pullback) {} persistable class Position extends G22TradingStrategy.Position { settable Juicer juicer; } Position openPosition(int direction) { if (nempty(openPositions())) { log("Not opening a second position"); null; } new Position p; p.juicer(new Juicer(maxLoss, pullback)); ret openPosition(p, direction); } void start { if (started()) fail("Already started"); if (currentPrice() == 0) ret with primed(true); // Save starting price, create price cells & digitizer startingPrice = currentPrice(); var priceCells = makePriceCells(startingPrice); digitizer = new PriceDigitizer2(priceCells); digitizer.verbose(verbose); log("Starting CHASER at " + startingPrice + " +/- " + cellSize); } void price(double price) { if (currentPrice == price) ret; currentPrice = price; if (!started()) { if (primed) { primed(false); start(); } ret; } digitizer.digitize(price); direction = sign(digitizedPrice()-lastDigitizedPrice()); nextStep(); if (started()) step(); print(this); } swappable void step { // Find positions to close L toClose = new L; /*for (p : p.juicer.closeReasons(p)) { cast p to Position; p.closeReason("WIN"); log("Closing winner position at " + currentPrice + " (" + p1 + " -> " + p2 + "): " + p); toClose.add(p); }*/ double p1 = lastDigitizedPrice(); double p2 = digitizedPrice(); direction = sign(p2-p1); if (direction == 0) ret; closePositions(toClose); // TODO: open new position afterStep(); } S baseToString() { ret colonCombine( _conceptID() == 0 ? "" : "Strategy " + _conceptID(), "Chaser"); } // Chaser.toString toString { ret baseToString(); } Position openShort() { ret openPosition(-1); } Position openLong() { ret openPosition(1); } }