Libraryless. Click here for Pure Java version (17529L/101K).
1 | persistable sclass TradingCandleMaker { |
2 | settable double candleLength = 1; // in minutes |
3 | settable int maxCandles = Int.MAX_VALUE; |
4 | settable double alignment; // shift in seconds |
5 | |
6 | // candleLength = granularity in minutes |
7 | *(double *candleLength) {} |
8 | |
9 | L<TradingCandle> candles = syncL(); |
10 | |
11 | TradingCandle currentCandle() { ret last(candles); } |
12 | TradingCandle completedCandle() { ret nextToLast(candles); } |
13 | bool isEmpty() { ret main isEmpty(candles); } |
14 | |
15 | Timestamp endTime() { |
16 | var candle = last(candles); |
17 | ret candle?.endTime(); |
18 | } |
19 | |
20 | double lastPrice() { ret currentCandle().end(); } |
21 | |
22 | void add(double price, long timestamp) { |
23 | var ts = new Timestamp(timestamp); |
24 | int safety = 0; |
25 | while (currentCandle() != null) { |
26 | if (safety++ >= 1000) { |
27 | warn("TradingCandleMaker safety warning"); |
28 | break; |
29 | } |
30 | Timestamp maxEnd = maxEndOfCurrentCandle(); |
31 | if (!greaterOrEq(ts, maxEnd)) break; |
32 | |
33 | currentCandle().endTime(maxEnd); |
34 | double lastPrice = lastPrice(); |
35 | newCandle(); |
36 | var cc = currentCandle(); |
37 | cc.addValue(lastPrice, maxEnd); |
38 | if (cc.projectedEndTime() == 0) |
39 | cc.projectedEndTime(maxEndOfCurrentCandle().unixDate()); |
40 | } |
41 | |
42 | if (empty(candles)) newCandle(); |
43 | currentCandle().addValue(price, ts); |
44 | } |
45 | |
46 | void newCandle { |
47 | var c = currentCandle(); |
48 | c?.ongoing(false).projectedEndTime(0); |
49 | candles.add(new TradingCandle().ongoing(true)); |
50 | dropOldCandles(); |
51 | } |
52 | |
53 | // returns number of entries processed |
54 | int addTickerSequence aka add aka feed(TickerSequence ts) { |
55 | int entriesProcessed = 0; |
56 | Timestamp endTime = endTime(); |
57 | |
58 | // TODO: Cut off beginning of ticker according to maxCandles |
59 | |
60 | if (endTime != null) |
61 | ts = ts.subSequenceFromTimestamp(endTime().unixDate()+1); |
62 | |
63 | int n = l(ts); |
64 | for i to n: { |
65 | add(ts.prices.get(i), ts.timestamps.get(i)); |
66 | ++entriesProcessed; |
67 | } |
68 | |
69 | if (!isEmpty() && ts.lastTickerEvent > currentCandle().endTime().toLong()) { |
70 | add(ts.lastPrice(), ts.lastTickerEvent); |
71 | ++entriesProcessed; |
72 | } |
73 | |
74 | ret entriesProcessed; |
75 | } |
76 | |
77 | Timestamp maxEndOfCurrentCandle() { |
78 | long time = currentCandle().startTime.toLong(); |
79 | long align = secondsToMS(alignment); |
80 | time = roundUpTo(secondsToMS(candleLength*60), time+align+1)-align; |
81 | ret new Timestamp(time); |
82 | } |
83 | |
84 | /*bool needNewCandle(long timestamp) { |
85 | ret empty(candles) |
86 | || timestamp >= maxEndOfCurrentCandle().unixDate(); |
87 | }*/ |
88 | |
89 | void dropOldCandles { |
90 | if (l(candles) > maxCandles) |
91 | removeSubList(candles, 0, l(candles)-maxCandles); |
92 | } |
93 | |
94 | L<TradingCandle> candles aka get() { ret cloneList(candles); } |
95 | L<TradingCandle> liveCandles() { ret candles; } |
96 | |
97 | // only complete candles (cut off last candle and also first candle if incomplete) |
98 | L<TradingCandle> completeCandles() { |
99 | synchronized(mutex()) { |
100 | int startIdx = isComplete(first(candles)) ? 0 : 1; |
101 | ret cloneSubList(candles, startIdx, l(candles)-1); |
102 | } |
103 | } |
104 | |
105 | // We just synchronize on the candles list |
106 | O mutex() { ret candles; } |
107 | |
108 | bool isComplete(TradingCandle candle) { |
109 | ret candle != null && candle.durationInSeconds() == candleLength*60; |
110 | } |
111 | |
112 | toString { ret "Candle maker " + formatDouble(candleLength) + "m, " + nCandles(candles); } |
113 | |
114 | L<TradingCandle> get(TickerSequence ticker) { |
115 | feed(ticker); |
116 | ret candles(); |
117 | } |
118 | |
119 | selfType granularity(double minutes) { |
120 | ret candleLength(minutes); |
121 | } |
122 | } |
download show line numbers debug dex old transpilations
Travelled to 3 computer(s): elmgxqgtpvxh, mqqgnosmbjvj, wnsclhtenguj
No comments. add comment
Snippet ID: | #1036143 |
Snippet name: | TradingCandleMaker - puts ticker values into candles of fixed length |
Eternal ID of this version: | #1036143/30 |
Text MD5: | 3e74364ba4cb81b4ce5bfafbdb8cc229 |
Transpilation MD5: | f15b774f3e9ca9e6547586990f6b703f |
Author: | stefan |
Category: | javax |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2023-03-20 21:40:43 |
Source code size: | 3632 bytes / 122 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 228 / 421 |
Version history: | 29 change(s) |
Referenced in: | [show references] |