concept RunnerTradingAlgorithm extends G22TradingStrategy { settableWithVar int minRun = 5; settableWithVar int bet; // direction: -1 or 1 for normal short or long // To change size of of position, use -2, 2 etc Position openPosition(int direction) { if (direction == 0) null; new Position p; p.marginToUse = marginPerPosition*abs(direction); 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(); startTime = currentTime(); var priceCells = makePriceCells(startingPrice); print("Made price cells: " + priceCells); digitizer = new PriceDigitizer2(priceCells); digitizer.verbose(verbose); //digitizer.init(startingPrice); log("Starting RUNNER at " + startingPrice + " +/- " + cellSize + ", min run: " + minRun); } void price(double price) { if (currentPrice == price) ret; currentPrice = price; if (hasClosedItself()) ret; if (!started()) { if (primed) { primed(false); start(); } else ret; } digitizer.digitize(price); direction = sign(digitizedPrice()-lastDigitizedPrice()); // No cell move? if (direction == 0) ret with afterStep(); nextStep(); //printWithPrecedingNL("New digitized price: " + digitizedPrice()); if (started()) step(); print(this); } swappable void step { double p1 = lastDigitizedPrice(); double p2 = digitizedPrice(); direction = sign(p2-p1); if (direction == 0) ret; bet = makeBet(); applyBet(); } swappable void applyBet { double drift = drift(); if (sign(drift) != sign(bet)) { closeAllPositions(); openPosition(bet); } log(renderVars(+stepCount, +drift, +bet, +lastDirection, +direction, +run, +minRun, +longestRunSeen)); afterStep(); } double currentCellNumber() { ret toCellNumber(currentPrice()); } // Cell we're in int currentDigitizedCell() { ret iround(toCellNumber(digitizedPrice())); } int priceDirection() { ret sign(currentCellNumber()-currentDigitizedCell()); } // Cell we're currently moving to int targetCell() { ret currentDigitizedCell()+priceDirection(); } double targetPrice() { ret fromCellNumber(targetCell()); } // Coin profit when next target is reached double targetProfit() { ret coinProfitAtPrice(targetPrice()); } // Is profit currently going up or down int profitDirection() { ret sign(targetProfit()-coinProfit()); } // progress to next target in percent double progressInProfitDirection() { ret absDiff(currentCellNumber(), currentDigitizedCell())*100; } settableWithVar int lastDirection; settableWithVar int move; settableWithVar int run; settableWithVar int longestRunSeen; S fieldsToReset() { ret lines(ll(super.fieldsToReset(), [[lastDirection run bet longestRunSeen move]])); } swappable int makeBet() { move(direction); if (direction == lastDirection) ++run; else run = 1; longestRunSeen(max(longestRunSeen, run)); if (run >= minRun) bet = direction; if (bet != 0 && direction != bet) bet = 0; lastDirection = direction; ret bet; } }