set flag Reparse. sclass Corridor { record noeq Position(/*settable*/ double openingPrice, /*settable*/ double direction) { /*settable*/ double closingPrice = Double.NaN; bool closed() { ret !isNaN(closingPrice); } S type() { ret trading_directionToPositionType(direction); } double profitAtPrice(double price) { ret (price-openingPrice)*direction; } double profit() { ret profitAtPrice(closed() ? closingPrice : currentPrice()); } void close { if (closed()) fail("Can't close again"); openPositions.remove(this); closingPrice = currentPrice(); closedPositions.add(this); realizedProfit += profit(); } toString { ret renderFunctionCall( spaceCombine( closed() ? "Closed" : null, type() ), openingPrice, "profit=" + profit()); } } settable double ladderStep = 1; gettable double currentPrice = 0; gettable double startingPrice = Double.NaN; gettable double lastDirection; gettable double realizedProfit; new LinkedHashSet openPositions; new L closedPositions; Position openPosition(double direction) { ret addAndReturn(openPositions, new Position(currentPrice(), direction)); } Threshold addThreshold(double price, double direction, Runnable action) { var t = new Threshold(price, direction, action); thresholds.put(t.price, t); bool triggered = (lastDirection == 0 || lastDirection == direction) && absDiff(currentPrice, price) < epsilon; printVars addThreshold(+currentPrice, +price, +direction, +lastDirection, +triggered); if (triggered) t.trigger(); ret t; } bool started() { ret !isNaN(startingPrice); } void start { if (started()) fail("Already started"); startingPrice = currentPrice(); print("Starting CORRIDOR at " + price + " +/- " + ladderStep); openPosition(1); openPosition(-1); } int digitizePrice(double price) { ret iround((price-startingPrice)/ladderStep); } selfType currentPrice aka price(double price) { double oldPrice = currentPrice; if (oldPrice == price) this; currentPrice = price; int direction = sign(price-oldPrice); lastDirection = direction; int oldPriceDigitized = digitizePrice(oldPrice); int priceDigitized = digitizePrice(price); for (p : openPositions) { } this; } double unrealizedProfit() { ret doubleSum(map(openPositions, ->.profit())); } double profit() { ret realizedProfit+unrealizedProfit(); } LS status() { double up = unrealizedProfit(); ret ll( "Profit: " + realizedProfit+up, "Realized profit: " + realizedProfit + " from " + n2(closedPositions, "closed position"), "Unrealized profit: " + up + " in " + n2(openPositions, "open position"), ); } toString { ret commaCombine(status()); } }