Libraryless. Click here for Pure Java version (10137L/58K).
1 | sclass MPM { |
2 | gettable new PositionSet imaginaryPositions; |
3 | gettable new PositionSet realPositions; |
4 | |
5 | settable double cryptoPrice; |
6 | new DoubleBuffer cryptoPriceLog; |
7 | // -1, 0 [initial value only] or 1 |
8 | settable int cryptoDirection; |
9 | event cryptoDirectionChanged; |
10 | |
11 | settable double currentTime; |
12 | |
13 | settable double maxAllowedLoss = 1; // in percent |
14 | |
15 | Position newShort() { ret new Position().direction(-1); } |
16 | Position newLong() { ret new Position().direction(1); } |
17 | |
18 | abstract class CloseReason {} |
19 | class LossClose > CloseReason {} |
20 | class HappyClose > CloseReason {} |
21 | class RegularClose > CloseReason {} // pullback close |
22 | class KillClose > CloseReason {} // hard-closed for any reason |
23 | |
24 | settable double fees = 0.12; |
25 | settable double expectedSlippage = .1; // in percent before leverage |
26 | |
27 | class Position { |
28 | settable bool real; |
29 | |
30 | // -1 (short) or 1 (long) |
31 | settable int direction; |
32 | |
33 | settable double openingTime; |
34 | settable double openingPrice; |
35 | settable double lastPrice; |
36 | settable double closingTime; |
37 | settable double closingPrice; |
38 | |
39 | simplyCached double openingPriceWithFeesAndSlippage() { |
40 | ret openingPrice*(1+(fees+expectedSlippage)/100*direction); |
41 | } |
42 | |
43 | settable double relativeValue; |
44 | settable double maxRelativeValue = negativeInfinity(); |
45 | settable double minRelativeValue = infinity(); |
46 | settable double pullbackThreshold; |
47 | |
48 | // null when position is open, not null when position was closed |
49 | settable CloseReason closeReason; |
50 | |
51 | PositionSet motherList() { |
52 | ret real ? realPositions : imaginaryPositions; |
53 | } |
54 | |
55 | void close(CloseReason reason) { |
56 | closingTime(time()); |
57 | closingPrice(cryptoPrice); |
58 | closeReason(reason); |
59 | motherList().wasClosed(this); |
60 | } |
61 | |
62 | void imagine { |
63 | real(false); |
64 | launch(); |
65 | } |
66 | |
67 | void launch { |
68 | update(cryptoPrice); |
69 | motherList().add(this); |
70 | } |
71 | |
72 | void update(double cryptoPrice) { |
73 | lastPrice(cryptoPrice); |
74 | relativeValue((cryptoPrice/openingPriceWithFeesAndSlippage()-1)*direction*100); |
75 | maxRelativeValue(max(maxRelativeValue, relativeValue)); |
76 | minRelativeValue(min(minRelativeValue, relativeValue)); |
77 | pullbackThreshold(maxRelativeValue-pullback(this)); |
78 | } |
79 | |
80 | toString { |
81 | ret renderVars(+direction, +openingPrice, +openingPriceWithFeesAndSlippage(), +lastPrice, +relativeValue, +maxRelativeValue); |
82 | } |
83 | |
84 | void autoClose { |
85 | if (relativeValue < -maxAllowedLoss) |
86 | ret with close(new LossClose); |
87 | |
88 | if (relativeValue >= 0 |
89 | && relativeValue < pullbackThreshold) |
90 | ret with close(new RegularClose); |
91 | } |
92 | |
93 | bool isOpen() { ret closeReason == null; } |
94 | } // end of Position |
95 | |
96 | class PositionSet { |
97 | new LinkedHashSet<Position> positionsByDate; |
98 | new LinkedHashSet<Position> openPositions; |
99 | new LinkedHashSet<Position> closedPositions; |
100 | |
101 | void add(Position p) { |
102 | positionsByDate.add(p); |
103 | (p.isOpen() ? openPositions : closedPositions).add(p); |
104 | } |
105 | |
106 | void remove(Position p) { |
107 | positionsByDate.remove(p); |
108 | openPositions.remove(p); |
109 | closedPositions.remove(p); |
110 | } |
111 | |
112 | void wasClosed(Position p) { |
113 | openPositions.remove(p); |
114 | closedPositions.add(p); |
115 | } |
116 | } |
117 | |
118 | swappable double pullback(Position p) { ret 0.5; } |
119 | |
120 | double time() { |
121 | ret currentTime; |
122 | } |
123 | |
124 | void addTickerSequence(TickerSequence ts) { |
125 | int n = l(ts); |
126 | for i to n: |
127 | newCryptoPrice(ts.prices.get(i), ts.timestamps.get(i)); |
128 | } |
129 | |
130 | void newCryptoPrice(double price) { |
131 | newCryptoPrice(price, currentTime+1); |
132 | } |
133 | |
134 | void newCryptoPrice(double price, double time) { |
135 | currentTime(time); |
136 | |
137 | // don't store non-changes |
138 | if (price == cryptoPrice) ret; |
139 | |
140 | int direction = sign(cryptoPrice-price); |
141 | cryptoPriceLog.add(price); |
142 | cryptoPrice(price); |
143 | |
144 | for (p : allOpenPositions()) { |
145 | p.update(cryptoPrice); |
146 | p.autoClose(); |
147 | } |
148 | |
149 | if (direction != cryptoDirection) { |
150 | cryptoDirection(direction); |
151 | cryptoDirectionChanged(); |
152 | } |
153 | } |
154 | |
155 | L<Position> allPositions() { |
156 | ret concatLists(realPositions().positionsByDate, imaginaryPositions().positionsByDate); |
157 | } |
158 | |
159 | L<Position> allOpenPositions() { |
160 | ret concatLists(realPositions().openPositions, imaginaryPositions().openPositions); |
161 | } |
162 | |
163 | { init(); } |
164 | |
165 | void init { |
166 | onCryptoDirectionChanged(-> { |
167 | for (p : ll(newLong(), newShort())) |
168 | p.openingTime(time()).openingPrice(cryptoPrice).imagine(); |
169 | }); |
170 | } |
171 | |
172 | void printStatus { |
173 | print(toString()); |
174 | } |
175 | |
176 | toString { |
177 | ret combineWithSeparator(" + ", |
178 | n2(realPositions.positionsByDate, "real position"), |
179 | n2(imaginaryPositions.positionsByDate, "imaginary position")); |
180 | } |
181 | } |
download show line numbers debug dex old transpilations
Travelled to 3 computer(s): elmgxqgtpvxh, mqqgnosmbjvj, wnsclhtenguj
No comments. add comment
Snippet ID: | #1036123 |
Snippet name: | MPM Trading Bot [dev.] |
Eternal ID of this version: | #1036123/39 |
Text MD5: | 76ccefe7624497e3bf9f72d558a4fcee |
Transpilation MD5: | a9bef09bf56e2533816ae9d5d838221d |
Author: | someone |
Category: | |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2022-09-28 22:36:32 |
Source code size: | 4976 bytes / 181 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 217 / 464 |
Version history: | 38 change(s) |
Referenced in: | [show references] |