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

173
LINES

< > BotCompany Repo | #1036204 // Corridor2 - the "analog" version that doesn't digitize prices [dev., have to figure out first]

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

Libraryless. Click here for Pure Java version (9969L/55K).

1  
sclass Corridor2 {
2  
  settable double smallMove = 0.2;
3  
  settable int capacity = 6;
4  
  settable bool openTwoPositionsAtStart = true;
5  
  
6  
  record noeq Position(double openingPrice, double direction) {
7  
    double closingPrice = Double.NaN;
8  
    
9  
    bool closed() { ret !isNaN(closingPrice); }
10  
    S type() { ret trading_directionToPositionType(direction); }
11  
    
12  
    double profitAtPrice(double price) {
13  
      ret (price-openingPrice)*direction;
14  
    }
15  
    
16  
    double profit() {
17  
      ret profitAtPrice(closed() ? closingPrice : currentPrice());
18  
    }
19  
    
20  
    void close {
21  
      if (closed()) fail("Can't close again");
22  
      openPositionsMap(direction).remove(openingPrice);
23  
      closingPrice = currentPrice();
24  
      closedPositions.add(this);
25  
      realizedProfit += profit();
26  
      print(this);
27  
      printPositions();
28  
    }
29  
    
30  
    toString {
31  
      ret renderFunctionCall(
32  
        spaceCombine(
33  
          closed() ? "Closed" : null,
34  
          type()
35  
        ),
36  
        openingPrice,
37  
        "profit=" + profit());
38  
    }
39  
  }
40  
      
41  
  gettable double currentPrice = 0;
42  
  
43  
  gettable double lastPrice = Double.NaN;
44  
  gettable double startingPrice = Double.NaN;
45  
  gettable double realizedProfit;
46  
  gettable double maxDebtEncountered;
47  
  gettable int stepCount;
48  
  
49  
  // open positions sorted by direction and price
50  
  gettable new TreeMap<Double, Position> openLongs;
51  
  gettable new TreeMap<Double, Position> openShorts;
52  
  
53  
  gettable new L<Position> closedPositions;
54  
  gettable new DoubleBuffer priceHistory;
55  
  
56  
  TreeMap<Double, Position> openPositionsMap(double direction) {
57  
    if (direction > 0) ret openLongs;
58  
    if (direction < 0) ret openShorts;
59  
    fail("direction 0");
60  
  }
61  
  
62  
  Position openPosition(double direction) {
63  
    var p = new Position(currentPrice(), direction);
64  
    openPositionsMap(direction).put(p.openingPrice, p);
65  
    print("Opening " + p);
66  
    printPositions();
67  
    ret p;
68  
  }
69  
  
70  
  Position openShort() { ret openPosition(-1); }
71  
  Position openLong() { ret openPosition(1); }
72  
  
73  
  L<Position> openPositions() {
74  
    ret concatLists(values(openLongs), values(openShorts));
75  
  }
76  
  
77  
  void printPositions {
78  
    var positions = openPositions();
79  
    print(colonCombine(n2(positions, "open position"),
80  
      joinWithComma(positions)));
81  
  }
82  
  
83  
  double unrealizedProfit() {
84  
    ret doubleSum(map(openPositions(), ->.profit()));
85  
  }
86  
  
87  
  L<Position> negativePositions() {
88  
    ret filter(openPositions(), p -> p.profit() < 0);
89  
  }
90  
  
91  
  double debt() {
92  
    ret doubleSum(map(negativePositions(), ->.profit()));
93  
  }
94  
  
95  
  double profit() {
96  
    ret realizedProfit+unrealizedProfit();
97  
  }
98  
  
99  
  LS status() {
100  
    ret ll(
101  
      "Step " + n2(stepCount),
102  
      "Profit: " + profit(),
103  
      "Realized profit: " + realizedProfit + " from " + n2(closedPositions, "closed position"),
104  
      "Unrealized profit: " + unrealizedProfit() + " in " + n2(openPositions(), "open position"),
105  
      "Debt: " + debt(),
106  
    );
107  
  }
108  
  
109  
  toString { ret commaCombine(status()); } 
110  
  
111  
  void prices(double... prices) {
112  
    fOr (price : prices)
113  
      price(price);
114  
  }
115  
  
116  
  void currentPrice aka price(double price) {
117  
    lastPrice = currentPrice;
118  
    
119  
    if (lastPrice == price) ret;
120  
    
121  
    currentPrice = price;
122  
123  
    priceHistory.add(price);
124  
    ++stepCount;
125  
    printWithPrecedingNL(commaCombine(
126  
      "Step " + stepCount + ". Old price: " + lastPrice,
127  
      "New price: " + price));
128  
129  
    step();
130  
    maxDebtEncountered = max(maxDebtEncountered, debt());
131  
    print(this);
132  
  }
133  
  
134  
  bool started() { ret !isNaN(startingPrice); }
135  
  
136  
  void start {
137  
    if (started()) fail("Already started");
138  
    startingPrice = currentPrice();
139  
    print("Starting CORRIDOR at " + startingPrice + " +/- " + smallMove);
140  
    if (openTwoPositionsAtStart) {
141  
      openPosition(1);
142  
      openPosition(-1);
143  
    }
144  
  }
145  
  
146  
  int currentDirection() {
147  
    ret sign(currentPrice-lastPrice);
148  
  }
149  
  
150  
  L<Position> positionsAtPriceOrWorse(double direction, double price) {
151  
    var map = openPositionsMap(direction);
152  
    ret direction < 0
153  
      ? valuesList(map.tailMap(price, true))
154  
      : valuesList(map.headMap(price, true));
155  
  }
156  
  
157  
  // Algorithm-specific logic follows
158  
  
159  
  swappable void step {
160  
    // Close winning position(s)
161  
    
162  
    var positions = positionsAtPriceOrWorse(currentDirection(),
163  
      currentPrice()-currentDirection()*smallMove);
164  
    for (p : positions) p.close();
165  
    
166  
    // If we closed anything, open a position in reverse direction
167  
    if (nempty(positions)) {
168  
      openPosition(-currentDirection());
169  
    }
170  
      
171  
    // TODO: "travelling"
172  
  }
173  
}

Author comment

Began life as a copy of #1036196

download  show line numbers  debug dex  old transpilations   

Travelled to 2 computer(s): elmgxqgtpvxh, mqqgnosmbjvj

No comments. add comment

Snippet ID: #1036204
Snippet name: Corridor2 - the "analog" version that doesn't digitize prices [dev., have to figure out first]
Eternal ID of this version: #1036204/11
Text MD5: e1402bffeed571f1edb572b3837d6914
Transpilation MD5: 09659741521ca370c190286f3300a77b
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 23:26:03
Source code size: 4701 bytes / 173 lines
Pitched / IR pitched: No / No
Views / Downloads: 130 / 239
Version history: 10 change(s)
Referenced in: [show references]