Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

178
LINES

< > BotCompany Repo | #1036199 // Corridor [backup]

JavaX fragment (include) [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (10557L/53K).

1  
set flag Reparse.
2  
3  
sclass Corridor {
4  
  record noeq Position(/*settable*/ double openingPrice, /*settable*/ double direction) {
5  
    /*settable*/ double closingPrice = Double.NaN;
6  
    
7  
    bool closed() { ret !isNaN(closingPrice); }
8  
    S type() { ret trading_directionToPositionType(direction); }
9  
    
10  
    double profitAtPrice(double price) {
11  
      ret (price-openingPrice)*direction;
12  
    }
13  
    
14  
    double profit() {
15  
      ret profitAtPrice(closed() ? closingPrice : currentPrice());
16  
    }
17  
    
18  
    void close {
19  
      if (closed()) fail("Can't close again");
20  
      openPositions.remove(this);
21  
      closingPrice = currentPrice();
22  
      closedPositions.add(this);
23  
      realizedProfit += profit();
24  
    }
25  
    
26  
    toString {
27  
      ret renderFunctionCall(
28  
        spaceCombine(
29  
          closed() ? "Closed" : null,
30  
          type()
31  
        ),
32  
        openingPrice,
33  
        "profit=" + profit());
34  
    }
35  
  }
36  
      
37  
  record noeq Threshold(/*settable*/ double price, /*settable*/ double direction, Runnable action) {
38  
    void trigger {
39  
      print("Triggered at " + price + " " + direction + ": " + action); 
40  
      callF(action);
41  
    }
42  
  }
43  
  
44  
  settable double epsilon = 0.001;
45  
  settable double ladderStep = 1;
46  
  gettable double currentPrice = 0;
47  
  
48  
  gettable double lastDirection;
49  
  gettable double realizedProfit;
50  
  new L<Loop> loops;
51  
  new TreeMultiMap<Double, Threshold> thresholds;
52  
  new LinkedHashSet<Position> openPositions;
53  
  new L<Position> closedPositions;
54  
  
55  
  record noeq Loop(/*settable*/ double startingPrice, /*settable*/ double direction) {
56  
    Position position;
57  
    Loop successor;
58  
    
59  
    class Open is Runnable {
60  
      run {
61  
        if (position != null && !position.closed())
62  
          fail("Trying to re-open position: " + this);
63  
          
64  
        print("Opening position at " + currentPrice() + " by loop " + this);
65  
        position = openPosition(direction);
66  
        if (successor == null)
67  
          successor = new Loop(startingPrice+ladderStep, direction).init();
68  
      }
69  
      
70  
      toString { ret spaceCombine("Open", startingPrice, direction); }
71  
    }
72  
    
73  
    class Close is Runnable {
74  
      run {
75  
        if (position != null) {
76  
          print("Closing position at " + currentPrice() + " by loop " + this);
77  
          position.close();
78  
        }
79  
      }
80  
      
81  
      toString { ret spaceCombine("Close", startingPrice, direction); }
82  
    }
83  
    
84  
    selfType init() {
85  
      loops.add(this);
86  
      addThreshold(startingPrice, -direction, new Open);
87  
      addThreshold(startingPrice+ladderStep, direction, new Close);
88  
      
89  
      this;
90  
    }
91  
    
92  
    toString {
93  
      ret formatRecordVars("Loop",
94  
        +startingPrice,
95  
        +direction, 
96  
        +position,
97  
        succ := successor == null ?: "t"
98  
      );
99  
    }
100  
  }
101  
  
102  
  Position openPosition(double direction) {
103  
    ret addAndReturn(openPositions, new Position(currentPrice(), direction));
104  
  }
105  
  
106  
  Threshold addThreshold(double price, double direction, Runnable action) {
107  
    var t = new Threshold(price, direction, action);
108  
    thresholds.put(t.price, t);
109  
    bool triggered = (lastDirection == 0 || lastDirection == direction) && absDiff(currentPrice, price) < epsilon;
110  
    printVars addThreshold(+currentPrice, +price, +direction, +lastDirection, +triggered);
111  
    if (triggered)
112  
      t.trigger();
113  
    ret t;
114  
  }
115  
  
116  
  void start {
117  
    double price = currentPrice();
118  
    print("Starting CORRIDOR at " + price + " +/- " + ladderStep);
119  
    lastDirection = 0;
120  
    new Loop(price, 1).init();
121  
    new Loop(price, -1).init();
122  
  }
123  
  
124  
  selfType currentPrice aka price(double price) {
125  
    double oldPrice = currentPrice;
126  
    if (oldPrice == price) this;
127  
    
128  
    currentPrice = price;
129  
    int direction = sign(price-oldPrice);
130  
    lastDirection = direction;
131  
    NavigableMap<Double, L<Threshold>> map = thresholds.innerMap();
132  
    map = direction > 0
133  
      ? map.subMap(oldPrice, false, price, true)
134  
      : map.subMap(price, true, oldPrice, false);
135  
    var keys = keys(map);
136  
    LL<Threshold> thresholdsCrossed = valuesList(map);
137  
    if (direction < 0)
138  
      reverseInPlace(thresholdsCrossed);
139  
    
140  
    new L<Threshold> toExecute;
141  
    for (actions : thresholdsCrossed)
142  
      for (t : actions)
143  
        if (t.direction == direction)
144  
          toExecute.add(t);
145  
146  
    printWithPrecedingNL(commaCombine(
147  
      "New price: " + currentPrice,
148  
      "direction: " + direction,
149  
      "Thresholds crossed: " + keys,
150  
      n2(toExecute, "trigger")));
151  
    
152  
    for (t : toExecute) t.trigger();
153  
    
154  
    this;
155  
  }
156  
  
157  
  double unrealizedProfit() {
158  
    ret doubleSum(map(openPositions, ->.profit()));
159  
  }
160  
  
161  
  double profit() {
162  
    ret realizedProfit+unrealizedProfit();
163  
  }
164  
  
165  
  LS status() {
166  
    double up = unrealizedProfit();
167  
    ret ll(
168  
      "Profit: " + realizedProfit+up,
169  
      "Realized profit: " + realizedProfit + " from " + n2(closedPositions, "closed position"),
170  
      "Unrealized profit: " + up + " in " + n2(openPositions, "open position"),
171  
      //n2(loops, "loop"),
172  
      //n2(keysSize(thresholds), "threshold"),
173  
      //n2(l(thresholds), "threshold action"),
174  
    );
175  
  }
176  
  
177  
  toString { ret commaCombine(status()); }
178  
}

Author comment

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: 65 / 87
Referenced in: [show references]