Libraryless. Click here for Pure Java version (10557L/53K).
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()); } } record noeq Threshold(/*settable*/ double price, /*settable*/ double direction, Runnable action) { void trigger { print("Triggered at " + price + " " + direction + ": " + action); callF(action); } } settable double epsilon = 0.001; settable double ladderStep = 1; gettable double currentPrice = 0; gettable double lastDirection; gettable double realizedProfit; new L<Loop> loops; new TreeMultiMap<Double, Threshold> thresholds; new LinkedHashSet<Position> openPositions; new L<Position> closedPositions; record noeq Loop(/*settable*/ double startingPrice, /*settable*/ double direction) { Position position; Loop successor; class Open is Runnable { run { if (position != null && !position.closed()) fail("Trying to re-open position: " + this); print("Opening position at " + currentPrice() + " by loop " + this); position = openPosition(direction); if (successor == null) successor = new Loop(startingPrice+ladderStep, direction).init(); } toString { ret spaceCombine("Open", startingPrice, direction); } } class Close is Runnable { run { if (position != null) { print("Closing position at " + currentPrice() + " by loop " + this); position.close(); } } toString { ret spaceCombine("Close", startingPrice, direction); } } selfType init() { loops.add(this); addThreshold(startingPrice, -direction, new Open); addThreshold(startingPrice+ladderStep, direction, new Close); this; } toString { ret formatRecordVars("Loop", +startingPrice, +direction, +position, succ := successor == null ?: "t" ); } } 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; } void start { double price = currentPrice(); print("Starting CORRIDOR at " + price + " +/- " + ladderStep); lastDirection = 0; new Loop(price, 1).init(); new Loop(price, -1).init(); } selfType currentPrice aka price(double price) { double oldPrice = currentPrice; if (oldPrice == price) this; currentPrice = price; int direction = sign(price-oldPrice); lastDirection = direction; NavigableMap<Double, L<Threshold>> map = thresholds.innerMap(); map = direction > 0 ? map.subMap(oldPrice, false, price, true) : map.subMap(price, true, oldPrice, false); var keys = keys(map); LL<Threshold> thresholdsCrossed = valuesList(map); if (direction < 0) reverseInPlace(thresholdsCrossed); new L<Threshold> toExecute; for (actions : thresholdsCrossed) for (t : actions) if (t.direction == direction) toExecute.add(t); printWithPrecedingNL(commaCombine( "New price: " + currentPrice, "direction: " + direction, "Thresholds crossed: " + keys, n2(toExecute, "trigger"))); for (t : toExecute) t.trigger(); 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"), //n2(loops, "loop"), //n2(keysSize(thresholds), "threshold"), //n2(l(thresholds), "threshold action"), ); } toString { ret commaCombine(status()); } }
Began life as a copy of #1036196
download show line numbers debug dex old transpilations
Travelled to 2 computer(s): mqqgnosmbjvj, wnsclhtenguj
No comments. add comment
Snippet ID: | #1036199 |
Snippet name: | Corridor [backup] |
Eternal ID of this version: | #1036199/1 |
Text MD5: | df720143d023644cd40c4dc87b1dccde |
Transpilation MD5: | 3ae729a21689ec51e14d9fa44bfcac8d |
Author: | stefan |
Category: | javax / gazelle 22 |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2022-10-17 01:09:41 |
Source code size: | 5275 bytes / 178 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 151 / 213 |
Referenced in: | [show references] |