@steerprotocol/strategy-utils 2.2.1 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/nodejs.yml +9 -9
- package/.vscode/settings.json +0 -6
- package/CHANGELOG.md +41 -0
- package/assembly/utils/MarketFeedAggregator.ts +140 -0
- package/assembly/utils/Ranges.ts +1 -1
- package/assembly/utils/env.ts +23 -2
- package/assembly/utils/index.ts +1 -0
- package/assembly/utils/triggers.ts +438 -0
- package/index.js +11 -11
- package/package.json +6 -3
- package/readme.md +387 -0
- package/tests/debug.wasm +0 -0
- package/tests/index.test.ts +236 -26
- package/tests/utils.ts +607 -0
package/readme.md
ADDED
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
# Strategy Utility Functions API Reference
|
|
2
|
+
|
|
3
|
+
## Triggers.ts
|
|
4
|
+
|
|
5
|
+
Trigger logic is created and implemented with the expectation to reduce the number of unnecessary executions. If the state of a liquidity providing vault is acceptable, such trigger logic can be used to determine if action should be taken or not. This reduces gas costs and unnecessary on-chain executions. The trigger functions are designed to return `true` in the event action should be taken (the trigger condition is met). In the case of `false` the condition is satisfactory and the user can factor in their own logic or return `continue` to skip execution. If the trigger depends on some information set by the user like triggering only when the price is over a ceratin percentage from the current active range (see triggerFromPercentage), variables such as the percentage should be added to the strategy configuration.
|
|
6
|
+
|
|
7
|
+
### Example
|
|
8
|
+
|
|
9
|
+
Imagine we will have a SushiLiquidityManager that will have a very broad liquidity coverage that we wish to only execute when our positions are out of range from the current tick. To do this we can utilize `triggerPositionsInactive` to check for this condition. In order to use many of the trigger functions, we will need the current positions provided by the `Liquidity Manager Positions` data connector. Additionally, we will need the current tick provided by a `V3 Pool Current Tick` data connector. These will need to be configured at the creation of the vault. In our strategy's execute function, the resulting current positions and current tick will be passed in as parameters in the configured order. Armed with this data, we can use the trigger function and return continue if the execution logic is untriggered.
|
|
10
|
+
|
|
11
|
+
```assemblyscript
|
|
12
|
+
export function execute(_currentTick: string, _currentPositions: string, ...any other data connector results for custom logic...): string {
|
|
13
|
+
// parse our data connector results
|
|
14
|
+
const currentTick = parseInt(_currentTick);
|
|
15
|
+
currentPositions = parseActiveRange(_positions);
|
|
16
|
+
// handle null cases
|
|
17
|
+
...
|
|
18
|
+
// call triggerPositionsInactive to see if we should execute
|
|
19
|
+
if (triggerPositionsInactive(currentPositions, currentTick)) return 'continue'
|
|
20
|
+
// if we don't return continue, we will execute our main logic for determining the new positions to be minted
|
|
21
|
+
...
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
### `parseActiveRange(_positions: string): Position`
|
|
29
|
+
|
|
30
|
+
This function parses the active position range from the type of string output of `LM.getPositions()`. It takes a string parameter `_positions`, which is expected to be in the format `[[#,#,#],[#,#,#],[#,#,#]]`, representing the lower tick, upper tick, and weight of a liquidity manager's positions.
|
|
31
|
+
|
|
32
|
+
**Parameters**
|
|
33
|
+
|
|
34
|
+
- `_positions` (string): The string representation of positions in the format `[[#,#,#],[#,#,#],[#,#,#]]`.
|
|
35
|
+
|
|
36
|
+
**Returns**
|
|
37
|
+
|
|
38
|
+
- `Position`: An instance of the `Position` class representing the parsed active range, with the lowest starting tick and highest upper tick from the recieved set of positions. Weight is set to 100 by default.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
### `emptyCurrentPosition(currentPosition: Position): boolean`
|
|
43
|
+
|
|
44
|
+
This function checks if the current position is empty. It takes a `currentPosition` parameter of type `Position`.
|
|
45
|
+
|
|
46
|
+
**Parameters**
|
|
47
|
+
|
|
48
|
+
- `currentPosition` (Position): The current position to check.
|
|
49
|
+
|
|
50
|
+
**Returns**
|
|
51
|
+
|
|
52
|
+
- `boolean`: Returns `true` if the current position ticks are the same (empty position), indicating that action should be taken. Returns `false` otherwise.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
### `triggerFromDistance(currentPosition: Position, rebalanceWidth: i64, currentTick: i64): boolean`
|
|
57
|
+
|
|
58
|
+
This function triggers an action based on the distance between the current tick and the center of the position range. It compares the current tick to upper and lower trigger bounds calculated from the `rebalanceWidth` parameter.
|
|
59
|
+
|
|
60
|
+
**Parameters**
|
|
61
|
+
|
|
62
|
+
- `currentPosition` (Position): The current position.
|
|
63
|
+
- `rebalanceWidth` (i64): The width (distance) from the center of the position range to trigger an action.
|
|
64
|
+
- `currentTick` (i64): The current tick to compare against the trigger bounds.
|
|
65
|
+
|
|
66
|
+
**Returns**
|
|
67
|
+
|
|
68
|
+
- `boolean`: Returns `true` if the current tick is outside the trigger bounds, indicating that action should be taken. Returns `false` if the current tick is within the trigger bounds, indicating that execution should be skipped.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
### `triggerFromPercentage(currentPosition: Position, rebalancePercentage: f64, currentTick: i64): boolean`
|
|
73
|
+
|
|
74
|
+
This function triggers an action based on the percentage difference between the current tick and the center of the position range. It compares the current tick to upper and lower trigger bounds calculated from the `rebalancePercentage` parameter.
|
|
75
|
+
|
|
76
|
+
**Parameters**
|
|
77
|
+
|
|
78
|
+
- `currentPosition` (Position): The current position.
|
|
79
|
+
- `rebalancePercentage` (f64): The percentage difference from the center of the position range to trigger an action.
|
|
80
|
+
- `currentTick` (i64): The current tick to compare against the trigger bounds.
|
|
81
|
+
|
|
82
|
+
**Returns**
|
|
83
|
+
|
|
84
|
+
- `boolean`: Returns `true` if the current tick is outside the trigger bounds, indicating that action should be taken. Returns `false` if the current tick is within the trigger bounds, indicating that execution should be skipped.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
### `triggerPositionsInactive(currentPosition: Position, currentTick: i64): boolean`
|
|
89
|
+
|
|
90
|
+
This function triggers an action when the current tick is no longer within the current position range.
|
|
91
|
+
|
|
92
|
+
**Parameters**
|
|
93
|
+
|
|
94
|
+
- `currentPosition` (Position): The current position.
|
|
95
|
+
- `currentTick` (i64): The current tick to compare against the position range.
|
|
96
|
+
|
|
97
|
+
**Returns**
|
|
98
|
+
|
|
99
|
+
- `boolean`: Returns `true` if the current tick is outside the position range, indicating that action should be taken. Returns `false` if the current tick is within the position range, indicating that execution should be skipped.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
### `triggerFromSpecifiedPrice(triggerTick: i64, currentTick: i64, triggerOver: boolean): boolean`
|
|
104
|
+
|
|
105
|
+
This function triggers an action when the current tick goes over or under a specified trigger tick.
|
|
106
|
+
|
|
107
|
+
**Parameters**
|
|
108
|
+
|
|
109
|
+
- `triggerTick` (i64): The trigger tick to compare against the current tick.
|
|
110
|
+
- `currentTick` (i64): The current tick to compare against the trigger tick.
|
|
111
|
+
- `triggerOver` (boolean): Indicates whether the trigger should activate when the current tick is greater than the trigger tick (`true`), or when it is less than the trigger tick (`false`).
|
|
112
|
+
|
|
113
|
+
**Returns**
|
|
114
|
+
|
|
115
|
+
- `boolean`: Returns `true` if the trigger condition is met, indicating that action should be taken. Returns `false` otherwise.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
### `triggerPricePastPositions(currentPosition: Position, currentTick: i64, triggerOver: boolean): boolean`
|
|
120
|
+
|
|
121
|
+
This function triggers an action when the current tick goes over or under the current position's range. It only triggers in one direction.
|
|
122
|
+
|
|
123
|
+
**Parameters**
|
|
124
|
+
|
|
125
|
+
- `currentPosition` (Position): The current position.
|
|
126
|
+
- `currentTick` (i64): The current tick to compare against the position range.
|
|
127
|
+
- `triggerOver` (boolean): Indicates whether the trigger should activate when the current tick is greater than the position's end tick (`true`), or when it is less than the position's start tick (`false`).
|
|
128
|
+
|
|
129
|
+
**Returns**
|
|
130
|
+
|
|
131
|
+
- `boolean`: Returns `true` if the trigger condition is met, indicating that action should be taken. Returns `false` otherwise.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Math.ts
|
|
136
|
+
|
|
137
|
+
### `_getMax(arr: Array<f64>): f64`
|
|
138
|
+
|
|
139
|
+
This function calculates the maximum value in an array of floating-point numbers. It takes an array `arr` as input.
|
|
140
|
+
|
|
141
|
+
**Parameters**
|
|
142
|
+
|
|
143
|
+
- `arr` (Array<f64>): The array of floating-point numbers.
|
|
144
|
+
|
|
145
|
+
**Returns**
|
|
146
|
+
|
|
147
|
+
- `f64`: The maximum value in the array.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
### `getMax(a: f64, b: f64): f64`
|
|
152
|
+
|
|
153
|
+
This function returns the maximum value between two floating-point numbers `a` and `b`.
|
|
154
|
+
|
|
155
|
+
**Parameters**
|
|
156
|
+
|
|
157
|
+
- `a` (f64): The first floating-point number.
|
|
158
|
+
- `b` (f64): The second floating-point number.
|
|
159
|
+
|
|
160
|
+
**Returns**
|
|
161
|
+
|
|
162
|
+
- `f64`: The maximum value between `a` and `b`.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
### `_normalDensity(std: f64, mean: f64, x: f64): f64`
|
|
167
|
+
|
|
168
|
+
This function calculates the value of the normal density function for a given standard deviation (`std`), mean (`mean`), and input value (`x`).
|
|
169
|
+
|
|
170
|
+
**Parameters**
|
|
171
|
+
|
|
172
|
+
- `std` (f64): The standard deviation.
|
|
173
|
+
- `mean` (f64): The mean.
|
|
174
|
+
- `x` (f64): The input value.
|
|
175
|
+
|
|
176
|
+
**Returns**
|
|
177
|
+
|
|
178
|
+
- `f64`: The value of the normal density function.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### `_standardDeviation(list: f64[]): f64`
|
|
183
|
+
|
|
184
|
+
This function calculates the standard deviation for an array of floating-point numbers (`list`).
|
|
185
|
+
|
|
186
|
+
**Parameters**
|
|
187
|
+
|
|
188
|
+
- `list` (f64[]): The array of floating-point numbers.
|
|
189
|
+
|
|
190
|
+
**Returns**
|
|
191
|
+
|
|
192
|
+
- `f64`: The standard deviation of the input array.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
### `_mean(list: f64[]): f64`
|
|
197
|
+
|
|
198
|
+
This function calculates the mean (average) of an array of floating-point numbers (`list`).
|
|
199
|
+
|
|
200
|
+
**Parameters**
|
|
201
|
+
|
|
202
|
+
- `list` (f64[]): The array of floating-point numbers.
|
|
203
|
+
|
|
204
|
+
**Returns**
|
|
205
|
+
|
|
206
|
+
- `f64`: The mean (average) of the input array.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
### `closestDivisibleNumber(num: number, divisor: number, floor: boolean): number`
|
|
211
|
+
|
|
212
|
+
This function finds the closest number to `num` that is divisible by `divisor`. If `floor` is `true`, the function returns the closest lower divisible number; otherwise, it returns the closest higher divisible number.
|
|
213
|
+
|
|
214
|
+
**Parameters**
|
|
215
|
+
|
|
216
|
+
- `num` (number): The number for which to find the closest divisible number.
|
|
217
|
+
- `divisor` (number): The divisor used to determine divisibility.
|
|
218
|
+
- `floor` (boolean): Indicates whether to return the closest lower divisible number (`true`) or the closest higher divisible number (`false`).
|
|
219
|
+
|
|
220
|
+
**Returns**
|
|
221
|
+
|
|
222
|
+
- `number`: The closest divisible number to `num` based on the specified divisor and rounding rule.
|
|
223
|
+
|
|
224
|
+
## Ranges.ts
|
|
225
|
+
|
|
226
|
+
### `getAverageTrueRange(candles: Array<Candle>): f64`
|
|
227
|
+
|
|
228
|
+
This function calculates the average true range (ATR) based on an array of Candle objects (`candles`).
|
|
229
|
+
|
|
230
|
+
**Parameters**
|
|
231
|
+
|
|
232
|
+
- `candles` (Array<Candle>): An array of Candle objects representing price data.
|
|
233
|
+
|
|
234
|
+
**Returns**
|
|
235
|
+
|
|
236
|
+
- `f64`: The average true range (ATR) value.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
### `trailingStop(percent: f64, prices: Candle[]): f64`
|
|
241
|
+
|
|
242
|
+
This function calculates the trailing stop price based on a specified percentage (`percent`) and an array of Candle objects (`prices`).
|
|
243
|
+
|
|
244
|
+
**Parameters**
|
|
245
|
+
|
|
246
|
+
- `percent` (f64): The percentage used to calculate the trailing stop price.
|
|
247
|
+
- `prices` (Candle[]): An array of Candle objects representing price data.
|
|
248
|
+
|
|
249
|
+
**Returns**
|
|
250
|
+
|
|
251
|
+
- `f64`: The trailing stop price.
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
### `trueRange(price: Candle): f64`
|
|
256
|
+
|
|
257
|
+
This function calculates the true range based on a single Candle object (`price`).
|
|
258
|
+
|
|
259
|
+
**Parameters**
|
|
260
|
+
|
|
261
|
+
- `price` (Candle): A Candle object representing price data.
|
|
262
|
+
|
|
263
|
+
**Returns**
|
|
264
|
+
|
|
265
|
+
- `f64`: The true range value.
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
### `averageTrueRange(prices: Candle[]): f64`
|
|
270
|
+
|
|
271
|
+
This function calculates the average true range (ATR) based on an array of Candle objects (`prices`).
|
|
272
|
+
|
|
273
|
+
**Parameters**
|
|
274
|
+
|
|
275
|
+
- `prices` (Candle[]): An array of Candle objects representing price data.
|
|
276
|
+
|
|
277
|
+
**Returns**
|
|
278
|
+
|
|
279
|
+
- `f64`: The average true range (ATR) value.
|
|
280
|
+
|
|
281
|
+
## Candle.ts
|
|
282
|
+
|
|
283
|
+
### `Candle` class
|
|
284
|
+
|
|
285
|
+
This class represents a candlestick object that contains price data.
|
|
286
|
+
|
|
287
|
+
**Properties**
|
|
288
|
+
|
|
289
|
+
- `timestamp` (i64): The timestamp of the candle.
|
|
290
|
+
- `high` (f64): The highest price of the candle.
|
|
291
|
+
- `low` (f64): The lowest price of the candle.
|
|
292
|
+
- `open` (f64): The opening price of the candle.
|
|
293
|
+
- `close` (f64): The closing price of the candle.
|
|
294
|
+
- `volume` (f64): The trading volume of the candle.
|
|
295
|
+
|
|
296
|
+
**Constructor**
|
|
297
|
+
|
|
298
|
+
- `Candle(timestamp: i64, high: f64, low: f64, open: f64, close: f64, volume: f64)`: Creates a new instance of the Candle class with the provided parameters.
|
|
299
|
+
|
|
300
|
+
**Methods**
|
|
301
|
+
|
|
302
|
+
- `toString(): string`: Returns a string representation of the Candle object.
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
### `parsePrices(_data: string): Array<Candle>`
|
|
307
|
+
|
|
308
|
+
This function parses the data connector data array in string format (`_data`) and returns an array of Candle objects.
|
|
309
|
+
|
|
310
|
+
**Parameters**
|
|
311
|
+
|
|
312
|
+
- `_data` (string): The data connector data array in string format.
|
|
313
|
+
|
|
314
|
+
**Returns**
|
|
315
|
+
|
|
316
|
+
- `Array<Candle>`: An array of Candle objects.
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
### `parseCandles(_data: string): Array<Candle>`
|
|
321
|
+
|
|
322
|
+
This function is an alias for `parsePrices(_data)` and performs the same functionality. It parses the data connector data array in string format (`_data`) and returns an array of Candle objects.
|
|
323
|
+
|
|
324
|
+
**Parameters**
|
|
325
|
+
|
|
326
|
+
- `_data` (string): The data connector data array in string format.
|
|
327
|
+
|
|
328
|
+
**Returns**
|
|
329
|
+
|
|
330
|
+
- `Array<Candle>`: An array of Candle objects.
|
|
331
|
+
|
|
332
|
+
## Position.ts
|
|
333
|
+
|
|
334
|
+
### `Position` class
|
|
335
|
+
|
|
336
|
+
This class represents a position with a start tick, end tick, and weight.
|
|
337
|
+
|
|
338
|
+
**Properties**
|
|
339
|
+
|
|
340
|
+
- `startTick` (i32): The starting tick of the position.
|
|
341
|
+
- `endTick` (i32): The ending tick of the position.
|
|
342
|
+
- `weight` (i32): The weight of the position.
|
|
343
|
+
|
|
344
|
+
**Constructor**
|
|
345
|
+
|
|
346
|
+
- `Position(startTick: i32, endTick: i32, weight: i32)`: Creates a new instance of the Position class with the provided parameters.
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## ExecutionContext.ts
|
|
351
|
+
|
|
352
|
+
### `ExecutionContext` class
|
|
353
|
+
|
|
354
|
+
This class represents the execution context containing various properties related to the execution environment.
|
|
355
|
+
|
|
356
|
+
**Properties**
|
|
357
|
+
|
|
358
|
+
- `executionTimestamp` (number): The execution timestamp.
|
|
359
|
+
- `epochLength` (number): The length of the epoch.
|
|
360
|
+
- `epochTimestamp` (i32): The epoch timestamp.
|
|
361
|
+
- `vaultAddress` (string): The vault address.
|
|
362
|
+
- `blockTime` (i32): The block time.
|
|
363
|
+
- `blockNumber` (i32): The block number.
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## SlidingWindow.ts
|
|
368
|
+
|
|
369
|
+
### `SlidingWindow<T>` class
|
|
370
|
+
|
|
371
|
+
This class represents a sliding window data structure that stores a fixed-size window of values of type `T`.
|
|
372
|
+
|
|
373
|
+
**Constructor**
|
|
374
|
+
|
|
375
|
+
- `SlidingWindow(windowSize: i32, formula: (window: Array<T>) => T)`: Creates a new instance of the SlidingWindow class with the specified window size and formula function.
|
|
376
|
+
|
|
377
|
+
**Methods**
|
|
378
|
+
|
|
379
|
+
- `addValue(value: T): void`: Adds a value to the sliding window.
|
|
380
|
+
- `getLastValue(): T`: Retrieves the last value added to the sliding window.
|
|
381
|
+
- `clear(): void`: Clears the sliding window, resetting all values to `null`.
|
|
382
|
+
- `setWindowSize(size: i32): void`: Sets the window size to the specified value.
|
|
383
|
+
- `getWindow(): Array<T>`: Retrieves the current window of values.
|
|
384
|
+
- `getFormulaResult(): T`: Calculates the formula result using the current window of values and the provided formula function.
|
|
385
|
+
- `isStable(): bool`: Checks if the sliding window is stable, i.e., if it contains the specified window size or more values.
|
|
386
|
+
|
|
387
|
+
Please note that the `SlidingWindow<T>` class is a generic class, allowing you to define the type of values stored in the sliding window.
|
package/tests/debug.wasm
ADDED
|
Binary file
|
package/tests/index.test.ts
CHANGED
|
@@ -1,28 +1,238 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
});
|
|
12
|
-
it("True average should compute properly", async () => {
|
|
13
|
-
const prices = [new myModule.Candle("12342343",1,2,3,4),new myModule.Candle("12342343",2,3,4,5)];
|
|
14
|
-
const trueAverage = myModule.getAverageTrueRange(prices, 1);
|
|
15
|
-
expect(trueAverage).toBe(2);
|
|
16
|
-
});
|
|
17
|
-
it("True average should support decimals ", async () => {
|
|
18
|
-
const prices = [new myModule.Candle("12342343",6.1,4.2,2.5,1.11),new myModule.Candle("12342343",41,32,41,15)];
|
|
19
|
-
const trueAverage = myModule.getAverageTrueRange(prices, 1);
|
|
20
|
-
expect(trueAverage).toBe(39.88999938964844)
|
|
21
|
-
});
|
|
22
|
-
it("Should parse candles ", async () => {
|
|
23
|
-
const candles = '[{"timestamp":"12312312123","high":6.1,"low":4.2,"open":2.5,"close":1.11},{"timestamp":"12312312123","high":41.1,"low":32.1,"open":41.2,"close":15.1}]'
|
|
24
|
-
const candlesArray = myModule.parseCandles(candles);
|
|
25
|
-
expect(candlesArray.length).toBe(2)
|
|
26
|
-
});
|
|
1
|
+
import { candles2, } from "./utils";
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import { WasmModule, loadWasm } from "@steerprotocol/app-loader";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
describe("Unit tests", () => {
|
|
7
|
+
let myModule: WasmModule;
|
|
8
|
+
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
myModule = await loadWasm(fs.readFileSync(__dirname + "/debug.wasm"), {})
|
|
27
11
|
});
|
|
12
|
+
|
|
13
|
+
describe("Trigger tests", () => {
|
|
14
|
+
// Testing the following options
|
|
15
|
+
// 'Current Price set distance from center of positions',
|
|
16
|
+
// 'Price leaves active range',
|
|
17
|
+
// 'Price moves percentage of active range away',
|
|
18
|
+
// 'Price moves one way past positions',
|
|
19
|
+
// 'None'
|
|
20
|
+
// TEST tirggers
|
|
21
|
+
test("Can return positions on none type", async () => {
|
|
22
|
+
const config = `{
|
|
23
|
+
"triggerStyle": "None",
|
|
24
|
+
"period":6,
|
|
25
|
+
"standardDeviations":2.0,
|
|
26
|
+
"liquidityShape": "Linear",
|
|
27
|
+
"poolFee": 3000,
|
|
28
|
+
"placementType": "Position over current price",
|
|
29
|
+
"positionSize": 600
|
|
30
|
+
}`
|
|
31
|
+
myModule.initialize(config);
|
|
32
|
+
const positions = '[[257100],[257300],[1]]'
|
|
33
|
+
const currentTick = '257301'
|
|
34
|
+
const timeSinceLastExecution = '5600'
|
|
35
|
+
const result = myModule.execute
|
|
36
|
+
(JSON.stringify(candles2), positions, currentTick, timeSinceLastExecution);
|
|
37
|
+
expect(result).not.toEqual('continue')
|
|
28
38
|
});
|
|
39
|
+
|
|
40
|
+
test
|
|
41
|
+
("Can return continue for active trigger", async () => {
|
|
42
|
+
const config = `{
|
|
43
|
+
"elapsedTendTime": 604800,
|
|
44
|
+
"triggerStyle": "Price leaves active range",
|
|
45
|
+
"strategy": "Classic",
|
|
46
|
+
"liquidityShape": "Linear",
|
|
47
|
+
"poolFee": 500,
|
|
48
|
+
"period":6,
|
|
49
|
+
"standardDeviations":2.0
|
|
50
|
+
}`
|
|
51
|
+
myModule.initialize(config);
|
|
52
|
+
const positions = '[[257100],[257300],[1]]'
|
|
53
|
+
const currentTick = '257251'
|
|
54
|
+
const timeSinceLastExecution = '5600'
|
|
55
|
+
const result = myModule.execute(//...[JSON.stringify(candles2), positions])
|
|
56
|
+
JSON.stringify(candles2),
|
|
57
|
+
positions,
|
|
58
|
+
currentTick,
|
|
59
|
+
timeSinceLastExecution);
|
|
60
|
+
expect(result).toEqual('continue')
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test("Can return positions for active trigger", async () => {
|
|
64
|
+
const config = `{
|
|
65
|
+
"elapsedTendTime": 604800,
|
|
66
|
+
"triggerStyle": "Price leaves active range",
|
|
67
|
+
"strategy": "Classic",
|
|
68
|
+
"liquidityShape": "Linear",
|
|
69
|
+
"poolFee": 3000,
|
|
70
|
+
"placementType": "Position over current price",
|
|
71
|
+
"period":6,
|
|
72
|
+
"standardDeviations":2.0,
|
|
73
|
+
"positionSize": 600
|
|
74
|
+
}`
|
|
75
|
+
myModule.initialize(config);
|
|
76
|
+
const positions = '[[257100],[257300],[1]]'
|
|
77
|
+
const currentTick = '257301'
|
|
78
|
+
const timeSinceLastExecution = '5600'
|
|
79
|
+
const result = myModule.execute
|
|
80
|
+
(JSON.stringify(candles2), positions, currentTick, timeSinceLastExecution);
|
|
81
|
+
expect(result).not.toEqual('continue')
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("Can return continue for distance trigger", async () => {
|
|
85
|
+
const config = `{
|
|
86
|
+
"elapsedTendTime": 604800,
|
|
87
|
+
"triggerStyle": "Current Price set distance from center of positions",
|
|
88
|
+
"tickDistanceFromCenter": 100,
|
|
89
|
+
"strategy": "Classic",
|
|
90
|
+
"liquidityShape": "Linear",
|
|
91
|
+
"poolFee": 3000,
|
|
92
|
+
"placementType": "Position over current price",
|
|
93
|
+
"period":6,
|
|
94
|
+
"standardDeviations":2.0,
|
|
95
|
+
"positionSize": 600
|
|
96
|
+
}`
|
|
97
|
+
myModule.initialize(config);
|
|
98
|
+
const positions = '[[257100],[257300],[1]]'
|
|
99
|
+
const currentTick = '257251'
|
|
100
|
+
const timeSinceLastExecution = '5600'
|
|
101
|
+
const result = myModule.execute
|
|
102
|
+
(JSON.stringify(candles2), positions, currentTick, timeSinceLastExecution);
|
|
103
|
+
expect(result).toEqual('continue')
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test("Can return positions for distance trigger", async () => {
|
|
107
|
+
const config = `{
|
|
108
|
+
"elapsedTendTime": 604800,
|
|
109
|
+
"triggerStyle": "Current Price set distance from center of positions",
|
|
110
|
+
"tickDistanceFromCenter": 100,
|
|
111
|
+
"strategy": "Classic",
|
|
112
|
+
"liquidityShape": "Linear",
|
|
113
|
+
"poolFee": 3000,
|
|
114
|
+
"placementType": "Position over current price",
|
|
115
|
+
"period":6,
|
|
116
|
+
"standardDeviations":2.0,
|
|
117
|
+
"positionSize": 600
|
|
118
|
+
}`
|
|
119
|
+
myModule.initialize(config);
|
|
120
|
+
const positions = '[[257100],[257300],[1]]'
|
|
121
|
+
const currentTick = '257301'
|
|
122
|
+
const timeSinceLastExecution = '5600'
|
|
123
|
+
const result = myModule.execute
|
|
124
|
+
(JSON.stringify(candles2), positions, currentTick, timeSinceLastExecution);
|
|
125
|
+
expect(result).not.toEqual('continue')
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test("Can return continue for percentage trigger", async () => {
|
|
129
|
+
const config = `{
|
|
130
|
+
"elapsedTendTime": 604800,
|
|
131
|
+
"triggerStyle": "Price moves percentage of active range away",
|
|
132
|
+
"percentageOfPositionRangeToTrigger": 1,
|
|
133
|
+
"strategy": "Classic",
|
|
134
|
+
"liquidityShape": "Linear",
|
|
135
|
+
"poolFee": 3000,
|
|
136
|
+
"placementType": "Position over current price",
|
|
137
|
+
"period":6,
|
|
138
|
+
"standardDeviations":2.0,
|
|
139
|
+
"positionSize": 600
|
|
140
|
+
}`
|
|
141
|
+
myModule.initialize(config);
|
|
142
|
+
const positions = '[[257100],[257300],[1]]'
|
|
143
|
+
const currentTick = '257251'
|
|
144
|
+
const timeSinceLastExecution = '5600'
|
|
145
|
+
const result = myModule.execute
|
|
146
|
+
(JSON.stringify(candles2), positions, currentTick, timeSinceLastExecution);
|
|
147
|
+
expect(result).toEqual('continue')
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test("Can return positions for percentage trigger", async () => {
|
|
151
|
+
const config = `{
|
|
152
|
+
"elapsedTendTime": 604800,
|
|
153
|
+
"triggerStyle": "Price moves percentage of active range away",
|
|
154
|
+
"percentageOfPositionRangeToTrigger": 1,
|
|
155
|
+
"strategy": "Classic",
|
|
156
|
+
"liquidityShape": "Linear",
|
|
157
|
+
"poolFee": 3000,
|
|
158
|
+
"placementType": "Position over current price",
|
|
159
|
+
"period":6,
|
|
160
|
+
"standardDeviations":2.0,
|
|
161
|
+
"positionSize": 600
|
|
162
|
+
}`
|
|
163
|
+
myModule.initialize(config);
|
|
164
|
+
const positions = '[[257100],[257300],[1]]'
|
|
165
|
+
const currentTick = '257301'
|
|
166
|
+
const timeSinceLastExecution = '5600'
|
|
167
|
+
const result = myModule.execute
|
|
168
|
+
(JSON.stringify(candles2), positions, currentTick, timeSinceLastExecution);
|
|
169
|
+
expect(result).not.toEqual('continue')
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
test("Can return continue for one way inactive - active", async () => {
|
|
173
|
+
const config = `{
|
|
174
|
+
"elapsedTendTime": 604800,
|
|
175
|
+
"triggerStyle": "Price moves one way past positions",
|
|
176
|
+
"triggerWhenOver": true,
|
|
177
|
+
"poolFee": 3000,
|
|
178
|
+
"placementType": "Position over current price",
|
|
179
|
+
"period":6,
|
|
180
|
+
"standardDeviations":2.0,
|
|
181
|
+
"positionSize": 600
|
|
182
|
+
}`
|
|
183
|
+
myModule.initialize(config);
|
|
184
|
+
const positions = '[[257100],[257300],[1]]'
|
|
185
|
+
const currentTick = '257251'
|
|
186
|
+
const timeSinceLastExecution = '5600'
|
|
187
|
+
const result = myModule.execute
|
|
188
|
+
(JSON.stringify(candles2), positions, currentTick, timeSinceLastExecution);
|
|
189
|
+
expect(result).toEqual('continue')
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test("Can return continue for one way inactive - below", async () => {
|
|
193
|
+
const config = `{
|
|
194
|
+
"elapsedTendTime": 604800,
|
|
195
|
+
"triggerStyle": "Price moves one way past positions",
|
|
196
|
+
"triggerWhenOver": true,
|
|
197
|
+
"strategy": "Classic",
|
|
198
|
+
"liquidityShape": "Linear",
|
|
199
|
+
"poolFee": 3000,
|
|
200
|
+
"placementType": "Position over current price",
|
|
201
|
+
"triggerWhenOver": true,
|
|
202
|
+
"period":6,
|
|
203
|
+
"standardDeviations":2.0,
|
|
204
|
+
"positionSize": 600
|
|
205
|
+
}`
|
|
206
|
+
myModule.initialize(config);
|
|
207
|
+
const positions = '[[257100],[257300],[1]]'
|
|
208
|
+
const currentTick = '257000'
|
|
209
|
+
const timeSinceLastExecution = '5600'
|
|
210
|
+
const result = myModule.execute
|
|
211
|
+
(JSON.stringify(candles2), positions, currentTick, timeSinceLastExecution);
|
|
212
|
+
expect(result).toEqual('continue')
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
test("Can return positions for one way inactive - above", async () => {
|
|
216
|
+
const config = `{
|
|
217
|
+
"elapsedTendTime": 604800,
|
|
218
|
+
"triggerStyle": "Price moves one way past positions",
|
|
219
|
+
"triggerWhenOver": true,
|
|
220
|
+
"strategy": "Bollinger Band",
|
|
221
|
+
"liquidityShape": "Linear",
|
|
222
|
+
"poolFee": 500,
|
|
223
|
+
"placementType": "Position over current price",
|
|
224
|
+
"triggerWhenOver": true,
|
|
225
|
+
"lookback": 12,
|
|
226
|
+
"period":6,
|
|
227
|
+
"standardDeviations":2.0,
|
|
228
|
+
}`
|
|
229
|
+
myModule.initialize(config);
|
|
230
|
+
const positions = '[[257100],[257300],[1]]'
|
|
231
|
+
const currentTick = '257301'
|
|
232
|
+
const timeSinceLastExecution = '5600'
|
|
233
|
+
const result = myModule.execute
|
|
234
|
+
(JSON.stringify([...candles2]), positions, currentTick, timeSinceLastExecution);
|
|
235
|
+
expect(result).not.toEqual('continue')
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
});
|