@steerprotocol/strategy-utils 3.1.2 → 3.2.0

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.
Files changed (36) hide show
  1. package/.github/workflows/nodejs.yml +12 -12
  2. package/.vscode/settings.json +6 -0
  3. package/CHANGELOG.md +3 -45
  4. package/asconfig.json +11 -9
  5. package/assembly/index.ts +1 -0
  6. package/assembly/panoptic/host.ts +285 -0
  7. package/assembly/panoptic/index.ts +3 -0
  8. package/assembly/panoptic/methods.ts +64 -0
  9. package/assembly/panoptic/types.ts +911 -0
  10. package/assembly/utils/Math.ts +12 -17
  11. package/assembly/utils/MovingAverages.ts +26 -19
  12. package/assembly/utils/Ranges.ts +15 -15
  13. package/assembly/utils/UniswapLiquidityUtils.ts +48 -0
  14. package/assembly/utils/index.ts +1 -3
  15. package/assembly/utils/types/Position.ts +0 -3
  16. package/assembly/utils/types/Price.ts +54 -0
  17. package/assembly/utils/types/index.ts +1 -4
  18. package/index.js +3 -14
  19. package/package.json +10 -14
  20. package/scripts/build-docs.js +68 -0
  21. package/tests/fixtures/json-compat.ts +30 -0
  22. package/tests/fixtures/panoptic-consumer.ts +24 -0
  23. package/tests/index.test.ts +55 -227
  24. package/assembly/utils/CandleGenerator.ts +0 -60
  25. package/assembly/utils/MarketFeedAggregator.ts +0 -140
  26. package/assembly/utils/SlidingWindow.ts +0 -59
  27. package/assembly/utils/env.ts +0 -23
  28. package/assembly/utils/triggers.ts +0 -585
  29. package/assembly/utils/types/Candle.ts +0 -39
  30. package/assembly/utils/types/DataConnectorConfig.ts +0 -7
  31. package/assembly/utils/types/ExecutionContext.ts +0 -11
  32. package/assembly/utils/types/RawTradeData.ts +0 -14
  33. package/index.html +0 -10
  34. package/readme.md +0 -387
  35. package/tests/debug.wasm +0 -0
  36. package/tests/utils.ts +0 -607
@@ -1,585 +0,0 @@
1
- import { JSON } from "json-as";
2
- // import { Position } from "@steerprotocol/strategy-utils/assembly";
3
- import { Position } from "./types";
4
-
5
- // NOTE: Trigger functions return true when action should be taken, if false then the strategy can return 'continue' to skip exeuction
6
- // Implementation might look like the following:
7
- // const trigger = getTriggerStyle(configJson.triggerStyle)
8
- // const triggerObj = new TriggerConfigHelper(configJson.triggerWhenOver, configJson.tickPriceTrigger, configJson.percentageOfPositionRangeToTrigger, configJson.tickDistanceFromCenter, configJson.elapsedTendTime)
9
- // if (!shouldTriggerExecution(trigger, triggerObj, _positions, _currentTick, _timeSinceLastExecution)) return 'continue'
10
-
11
- // Gets active range from the output of LM.getPositions()
12
- // export function parseActiveRange(_positions: string): Position {
13
- // // _positions will be '[[#,#,#],[#,#,#],[#,#,#]]' presumably. lower, upper, weight
14
- // // clean up our list by removing spaces and brackets
15
- // let positions = _positions.replaceAll(' ','');
16
- // positions = positions.replaceAll('[','');
17
- // let rangeArray = positions.split(']',2);
18
- // let startTick = rangeArray[0].split(',')[0];
19
- // let endRange = rangeArray[1].split(']',2);
20
- // const endTicks = endRange[0].split(',');
21
- // let endTick = endTicks[endTicks.length-1]
22
- // // if trailing comma
23
- // if (endTick == '') endTick = endTicks[endTicks.length-2]
24
- // const strArrays = [startTick, endTick];
25
- // // check null
26
- // if (strArrays[0] == '' || strArrays[0] == null || strArrays[1] == '' || strArrays[1] == null) {
27
- // return new Position(0, 0, 0);
28
- // }
29
- // // else return normal
30
- // const lowerTick = i32(parseInt(strArrays[0]));
31
- // const upperTick = i32(parseInt(strArrays[1]));
32
- // // weights shouldn't matter in this context, we just want the total active range
33
- // return new Position(lowerTick, upperTick, 100);
34
- // }
35
-
36
- export function parseActiveRange(_positions: Array<Position>): Position {
37
-
38
- if (_positions.length == 0) return new Position(0, 0, 0);
39
- // get first pos start tick and last pos end
40
- let startTick = _positions[0].startTick
41
- let endTick = _positions[_positions.length - 1].endTick
42
-
43
- // weights shouldn't matter in this context, we just want the total active range
44
- return new Position(startTick, endTick, 100);
45
- }
46
-
47
- export function emptyCurrentPosition(currentPosition: Position): boolean {
48
- // return true if current position ticks are not the same
49
- return currentPosition.startTick == currentPosition.endTick
50
- }
51
-
52
- // where rebalance width is how far off on either side the trigger should activate
53
- export function triggerFromDistance(currentPosition: Position, rebalanceWidth: i64, currentTick: i64): boolean {
54
- if (emptyCurrentPosition(currentPosition)) return true
55
- const centerPosition = (currentPosition.endTick + currentPosition.startTick) / 2
56
- const upperTrigger = centerPosition + (rebalanceWidth)
57
- const lowerTrigger = centerPosition - (rebalanceWidth)
58
- // In bounds? return false to continue (skip exec), returns true to execute
59
- return !((currentTick <= upperTrigger && currentTick >= lowerTrigger))
60
- }
61
-
62
- // tick moves % away from center of position range
63
- export function triggerFromPercentage(currentPosition: Position, rebalancePercentage: f64, currentTick: i64): boolean {
64
- if (emptyCurrentPosition(currentPosition)) return true
65
- const side = (currentPosition.endTick - currentPosition.startTick) / 2
66
- const centerPosition = (currentPosition.endTick + currentPosition.startTick) / 2
67
- const triggerDiff = i64(Math.round(f64(side) * rebalancePercentage))
68
- const upperTrigger = centerPosition + triggerDiff
69
- const lowerTrigger = centerPosition - triggerDiff
70
- // In bounds? return false to continue (skip exec), returns true to execute
71
- return !((currentTick <= upperTrigger && currentTick >= lowerTrigger))
72
- }
73
-
74
- // when current tick is no longer in the current position range
75
- export function triggerPositionsInactive(currentPosition: Position, currentTick: i64): boolean {
76
- // return JSON.stringify(currentPosition)
77
- if (emptyCurrentPosition(currentPosition)) return true
78
-
79
- return (!((currentTick <= currentPosition.endTick && currentTick >= currentPosition.startTick)))
80
- }
81
-
82
- // when tick goes over or under specified tick, trigger rebalance
83
- // export function triggerFromSpecifiedPrice(triggerTick: i64, currentTick: i64, triggerOver: boolean): boolean {
84
- // // if trigger over, return true when currentTick > triggerTick
85
- // if (triggerOver) {
86
- // return currentTick > triggerTick
87
- // }
88
- // // trigger under, if current price is less than trigger tick return true
89
- // return triggerTick > currentTick
90
- // }
91
-
92
- // when tick goes over or under current positions, trigger rebalance, only moves one way
93
- export function triggerPricePastPositions(currentPosition: Position, currentTick: i64, triggerOver: boolean): boolean {
94
- if (emptyCurrentPosition(currentPosition)) return true
95
- if (triggerOver) {
96
- // if the currentTick is over the endTick, rebal
97
- return currentTick > i64(currentPosition.endTick)
98
- }
99
- // if current tick is under start tick
100
- return currentTick < i64(currentPosition.startTick)
101
- }
102
-
103
- export const enum TriggerStyle {
104
- DistanceFromCenterOfPositions,
105
- PercentageChangeFromPositionRange,
106
- PositionsInactive,
107
- // SpecificPrice,
108
- PricePastPositions,
109
- None,
110
- }
111
-
112
- // export function TriggerStyleLookup(triggerStyle: TriggerStyle): string {
113
- // switch (triggerStyle) {
114
- // case TriggerStyle.DistanceFromCenterOfPositions:
115
- // return "Distance from center of position(s)";
116
- // case TriggerStyle.PercentageChangeFromPositionRange:
117
- // return "Percentage of position(s)";
118
- // case TriggerStyle.PositionsInactive:
119
- // return "Positions Inactive";
120
- // // case TriggerStyle.SpecificPrice:
121
- // // return "Specific Price";
122
- // case TriggerStyle.PricePastPositions:
123
- // return "Price moved past position(s)";
124
- // case TriggerStyle.None:
125
- // return 'None'
126
-
127
- // default:
128
- // throw new Error(`Unknown trigger style: ${triggerStyle}`);
129
- // }
130
- // }
131
-
132
- // export class DistanceFromCenterOfPositionsOptions {
133
- // tickDistanceFromCenter: i64 = 0;
134
- // requiredDataTypes: string[] = ['Liquidity Manager Positions', 'V3 Pool Current Tick'];
135
- // }
136
-
137
- // export class PercentageChangeFromPositionRangeOptions {
138
- // percentageOfPositionRangeToTrigger: f64 = 0.0;
139
- // requiredDataTypes: string[] = ['Liquidity Manager Positions', 'V3 Pool Current Tick'];
140
- // }
141
-
142
- // export class PositionsInactiveOptions {
143
- // requiredDataTypes: string[] = ['Liquidity Manager Positions', 'V3 Pool Current Tick'];
144
- // }
145
-
146
- // export class SpecificPriceOptions {
147
- // tickPriceTrigger: i64 = 0;
148
- // triggerWhenOver: boolean = false;
149
- // requiredDataTypes: string[] = ['V3 Pool Current Tick'];
150
- // }
151
-
152
- // export class PricePastPositionsOptions {
153
- // triggerWhenOver: boolean = false;
154
- // requiredDataTypes: string[] = ['Liquidity Manager Positions', 'V3 Pool Current Tick'];
155
- // }
156
-
157
- // @ts-ignore
158
- @json
159
- export class TriggerConfigHelper {
160
- // triggerType: string = "Price leaves active range";
161
- triggerWhenOver: boolean = false;
162
- tickPriceTrigger: i64 = 0;
163
- percentageOfPositionRangeToTrigger: f64 = 0.0;
164
- tickDistanceFromCenter: i64 = 0;
165
- elapsedTendTime: i64 = 0;
166
- constructor( t: boolean, tpt: i64, poptrr:f64, tdfc: i64, ett: i64) {
167
- if(t) this.triggerWhenOver = t
168
- if(tpt) this.tickPriceTrigger = tpt
169
- if(poptrr) this.percentageOfPositionRangeToTrigger = poptrr
170
- if(tdfc) this.tickDistanceFromCenter = tdfc
171
- if(ett) this.elapsedTendTime = ett
172
- }
173
- }
174
-
175
- export function getTriggerExpectedDataTypes(triggerStyle: string): string[] {
176
- // get tirggerStyle
177
- const style = getTriggerStyle(triggerStyle)
178
- // currently we use only this list
179
- const typicalTypes = ["Liquidity Manager Positions", "V3 Pool Current Tick", "Time Since Last Execution"]
180
- switch (style) {
181
- case TriggerStyle.DistanceFromCenterOfPositions:
182
- return typicalTypes;
183
- case TriggerStyle.PercentageChangeFromPositionRange:
184
- return typicalTypes;
185
- case TriggerStyle.PositionsInactive:
186
- return typicalTypes;
187
- // case TriggerStyle.SpecificPrice:
188
- // return "Specific Price";
189
- case TriggerStyle.PricePastPositions:
190
- return typicalTypes;
191
- case TriggerStyle.None:
192
- // return no data connectors for none
193
- return [];
194
-
195
- default:
196
- throw new Error(`Unknown trigger style: ${triggerStyle}`);
197
- }
198
- }
199
-
200
- // currently implemented as :: ulm positions [0], current tick [1], time since last execution [2]
201
- // as more types are added this logic path with be redone
202
- export function shouldTriggerExecution(
203
- _triggerStyle: string,
204
- triggerOptions: TriggerConfigHelper,
205
- dataConnector1: Array<Position>,
206
- dataConnector2: i64,
207
- dataConnector3: i64) : boolean {
208
-
209
- // possible dc inputs
210
- let currentPositionRange: Position;
211
- let currentTick: i64;
212
- const triggerStyle = getTriggerStyle(_triggerStyle)
213
-
214
-
215
-
216
- let timeSinceLastExecution: i64;
217
-
218
- switch (triggerStyle) {
219
- case TriggerStyle.DistanceFromCenterOfPositions:
220
- // parse ulm positions [0], current tick [1]
221
- // @ts-ignore
222
- timeSinceLastExecution = i64((dataConnector3))
223
- if (timeSinceLastExecution >= i64(triggerOptions.elapsedTendTime)) return true
224
- currentPositionRange = parseActiveRange(dataConnector1)
225
- currentTick = i64((dataConnector2))
226
- return triggerFromDistance(currentPositionRange, triggerOptions.tickDistanceFromCenter, currentTick)
227
-
228
- case TriggerStyle.PercentageChangeFromPositionRange:
229
- // parse ulm positions [0], current tick [1]
230
- timeSinceLastExecution = i64((dataConnector3))
231
- if (timeSinceLastExecution >= i64(triggerOptions.elapsedTendTime)) return true
232
- currentPositionRange= parseActiveRange(dataConnector1)
233
- currentTick = i64((dataConnector2))
234
- return triggerFromPercentage(currentPositionRange, triggerOptions.percentageOfPositionRangeToTrigger, currentTick)
235
-
236
- case TriggerStyle.PositionsInactive:
237
- // parse ulm positions [0], current tick [1]
238
- timeSinceLastExecution = i64((dataConnector3))
239
- if (timeSinceLastExecution >= i64(triggerOptions.elapsedTendTime)) return true
240
- currentPositionRange = parseActiveRange(dataConnector1)
241
- currentTick = i64((dataConnector2))
242
- return triggerPositionsInactive(currentPositionRange, currentTick)
243
-
244
- case TriggerStyle.PricePastPositions:
245
- // parse ulm positions [0], current tick [1]
246
- timeSinceLastExecution = i64((dataConnector3))
247
- if (timeSinceLastExecution >= i64(triggerOptions.elapsedTendTime)) return true
248
- currentPositionRange = parseActiveRange(dataConnector1)
249
- currentTick = i64((dataConnector2))
250
- return triggerPricePastPositions(currentPositionRange, currentTick, triggerOptions.triggerWhenOver)
251
- default:
252
- return true
253
- }
254
- }
255
-
256
- export function getTriggerStyle(trigger: string): TriggerStyle {
257
- if (trigger === 'Current Price set distance from center of positions') {
258
- return TriggerStyle.DistanceFromCenterOfPositions;
259
- } else if (trigger === 'Price leaves active range') {
260
- return TriggerStyle.PositionsInactive;
261
- } else if (trigger === 'Price moves percentage of active range away') {
262
- return TriggerStyle.PercentageChangeFromPositionRange;
263
- } else if (trigger === 'Price moves one way past positions') {
264
- return TriggerStyle.PricePastPositions;
265
- } else {
266
- return TriggerStyle.None;
267
- }
268
- }
269
-
270
- function getTriggerName(trigger: TriggerStyle): string {
271
- if (trigger === TriggerStyle.DistanceFromCenterOfPositions) {
272
- return 'Current Price set distance from center of positions';
273
- } else if (trigger === TriggerStyle.PositionsInactive) {
274
- return 'Price leaves active range';
275
- } else if (trigger === TriggerStyle.PercentageChangeFromPositionRange) {
276
- return 'Price moves percentage of active range away';
277
- } else if (trigger === TriggerStyle.PricePastPositions) {
278
- return 'Price moves one way past positions';
279
- } else {
280
- return 'None';
281
- }
282
- }
283
-
284
- function expectedDataTypesHelper(strategyDataConnectors: string[], triggerStyle: string): string[] {
285
- // const style = getTriggerStyle(triggerStyle)
286
- return strategyDataConnectors.concat(getTriggerExpectedDataTypes(triggerStyle))
287
- // return `"expectedDataTypes": {
288
- // "hidden": true,
289
- // "type": "string",
290
- // "default": "${(fullDataTypes).toString()}",
291
- // "const": "${(fullDataTypes).toString()}"
292
- // }`
293
- }
294
-
295
- // @serializable
296
- // export class TriggerInfo {
297
- // name: string = '';
298
- // expectedDataTypes: string[] = [];
299
- // constructor (_name: string, _expectedDataTypes: string[]) {
300
- // this.name = _name
301
- // this.expectedDataTypes = _expectedDataTypes
302
- // }
303
- // }
304
-
305
- export function triggerPropertyHelper(): string {
306
- // export function triggerPropertyHelper(strategyDataTypes: string[], omit: TriggerStyle[] = []): string {
307
- // const triggerList = [
308
- // TriggerStyle.DistanceFromCenterOfPositions,
309
- // TriggerStyle.None,
310
- // TriggerStyle.PercentageChangeFromPositionRange,
311
- // TriggerStyle.PositionsInactive,
312
- // TriggerStyle.PricePastPositions,
313
- // ];
314
-
315
- const triggersObjects: string[] = [
316
- 'Current Price set distance from center of positions',
317
- 'Price leaves active range',
318
- 'Price moves percentage of active range away',
319
- 'Price moves one way past positions',
320
- 'None',
321
- ];
322
-
323
- const triggerStrings = [
324
- 'Current Price set distance from center of positions',
325
- 'Price leaves active range',
326
- 'Price moves percentage of active range away',
327
- 'Price moves one way past positions',
328
- 'None'
329
- ]
330
-
331
- // return `"triggerStyle": {
332
- // "enumNames": ${JSON.stringify(triggerStrings)},
333
- // "enum": ${JSON.stringify(triggersObjects)},
334
- // "type": "string",
335
- // "title": "Logic to trigger new positions",
336
- // "default": "None"
337
- // }`;
338
-
339
- return `"triggerStyle": {
340
- "enumNames": [
341
- "Trigger when price moves set distance away from center of liquidity range",
342
- "Trigger when price leaves active liquidity range",
343
- "Trigger when price moves a proportion of active liquidity range away",
344
- "Trigger when price moves out of active range only in one direction",
345
- "None"
346
- ],
347
- "enum": [
348
- "Current Price set distance from center of positions",
349
- "Price leaves active range",
350
- "Price moves percentage of active range away",
351
- "Price moves one way past positions",
352
- "None"
353
- ],
354
- "type": "string",
355
- "title": "Logic to trigger new positions",
356
- "default": "None"
357
- }`
358
- }
359
-
360
- export function configDefinitions(): string {
361
- return `
362
- "elapsedTendTime": {
363
- "type": "number",
364
- "title": "Max time between tends",
365
- "description": "If trigger conditions have not been met for this period of time, the strategy will execute regardless of trigger logic to update vault accounting.",
366
- "default": 1209600
367
- },
368
- "bins": {
369
- "type": "number",
370
- "title": "Positions",
371
- "description": "The max number of positions the strategy will make to achieve the desired curve.",
372
- "detailedDescription": "The strategy will attempt to make this number of positions, but can be limited by available range and pool spacing"
373
- },
374
- "reflect": {
375
- "title": "Reflect Curve Over Y-Axis",
376
- "type": "boolean",
377
- "default": false
378
- },
379
- "invert": {
380
- "title": "Invert Curve Over X-Axis",
381
- "type": "boolean",
382
- "default": false
383
- }`
384
- }
385
-
386
- export function triggerDependency(): string {
387
- return `"triggerStyle": {
388
- "oneOf": [
389
- {
390
- "properties": {
391
- "triggerStyle": {
392
- "const": "None"
393
- }
394
- },
395
- "required": []
396
- },
397
- {
398
- "properties": {
399
- "triggerStyle": {
400
- "const": "Current Price set distance from center of positions"
401
- },
402
- "tickDistanceFromCenter": {
403
- "type": "integer",
404
- "title": "Tick Distance",
405
- "description": "The number of basis points (ticks) away from the central price of existing positions",
406
- "detailedDescription": "The trigger mechanism for new positions is based on a fixed number of ticks from the midpoint of the active range. For instance, with a position range of 0-100 and a tick distance set at 75, the trigger points are calculated 75 ticks on either side of the central tick of our positions, which is 50. This establishes a trigger range extending from -25 to 125. Any current tick falling within this range will not prompt execution. The center of this trigger range is dynamically adjusted based on the locations of future positions."
407
- },
408
- "elapsedTendTime": {
409
- "$ref": "#/definitions/elapsedTendTime"
410
- }
411
- },
412
- "required": [
413
- "tickDistanceFromCenter",
414
- "elapsedTendTime"
415
- ]
416
- },
417
- {
418
- "properties": {
419
- "triggerStyle": {
420
- "const": "Price leaves active range"
421
- },
422
- "elapsedTendTime": {
423
- "$ref": "#/definitions/elapsedTendTime"
424
- }
425
- },
426
- "required": [
427
- "elapsedTendTime"
428
- ]
429
- },
430
- {
431
- "properties": {
432
- "triggerStyle": {
433
- "const": "Price moves percentage of active range away"
434
- },
435
- "percentageOfPositionRangeToTrigger": {
436
- "type": "number",
437
- "title": "Percentage of Range",
438
- "description": "Specify the percentage of the total range at which to initiate new positions, where 100% or a value of 1 corresponds to the edge of the range.",
439
- "detailedDescription": "For a position with a range spanning from 0 to 100 ticks, setting this value to 1 will activate the trigger at the outermost bounds of the range. If the value is set to 0.5, the trigger range narrows to between 25 and 75 ticks. Conversely, setting the value to 2 expands the trigger range, extending it from -50 to 150 ticks."
440
- },
441
- "elapsedTendTime": {
442
- "$ref": "#/definitions/elapsedTendTime"
443
- }
444
- },
445
- "required": [
446
- "percentageOfPositionRangeToTrigger",
447
- "elapsedTendTime"
448
- ]
449
- },
450
- {
451
- "properties": {
452
- "triggerStyle": {
453
- "const": "Price moves one way past positions"
454
- },
455
- "triggerWhenOver": {
456
- "type": "boolean",
457
- "title": "Price Moves Higher",
458
- "description": "Set 'True' to initiate new positions when the current price (tick) exceeds the level of existing positions. Conversely, mark it as 'False' if new positions should be established when the price is lower than the current positions.",
459
- "detailedDescription": "When the existing position spans from 0 to 100 ticks, setting the parameter to 'True' will prompt the strategy to execute only if the current tick exceeds 100. In any scenario where the current tick is less than or equal to 100, the strategy will recommend to continue without executing new execution."
460
- },
461
- "elapsedTendTime": {
462
- "$ref": "#/definitions/elapsedTendTime"
463
- }
464
- },
465
- "required": [
466
- "triggerWhenOver",
467
- "elapsedTendTime"
468
- ]
469
- }
470
- ]
471
- }`
472
- }
473
-
474
- export function allOfTrigger(): string {
475
- return `{
476
- "if": {
477
- "properties": {
478
- "triggerStyle": {
479
- "const": "None"
480
- }
481
- }
482
- },
483
- "then": {
484
- "required": []
485
- }
486
- },
487
- {
488
- "if": {
489
- "properties": {
490
- "triggerStyle": {
491
- "const": "Current Price set distance from center of positions"
492
- }
493
- }
494
- },
495
- "then": {
496
- "properties": {
497
- "tickDistanceFromCenter": {
498
- "type": "integer",
499
- "title": "Tick Distance",
500
- "description": "The number of ticks (basis points) from center price of positions to trigger setting new positions",
501
- "detailedDescription": "The static number of ticks from the center of the active range to trigger: if our position goes from 0-100, and we have a tick distance of 75, we will go out 75 ticks both ways from the center of our positions (50). This means we will skip execution only if the current tick is between -25 and 125. Future positions will determine where the center of the trigger range is located."
502
- },
503
- "elapsedTendTime": {
504
- "type": "number",
505
- "title": "Max time between tends",
506
- "description": "If trigger conditions have not been met for this period of time, the strategy will execute regardless of trigger logic to update vault accounting.",
507
- "default": 1209600
508
- }
509
- },
510
- "required": ["tickDistanceFromCenter", "elapsedTendTime"]
511
- }
512
- },
513
- {
514
- "if": {
515
- "properties": {
516
- "triggerStyle": {
517
- "const": "Price leaves active range"
518
- }
519
- }
520
- },
521
- "then": {
522
- "properties": {
523
- "elapsedTendTime": {
524
- "type": "number",
525
- "title": "Max time between tends",
526
- "description": "If trigger conditions have not been met for this period of time, the strategy will execute regardless of trigger logic to update vault accounting.",
527
- "default": 1209600
528
- }
529
- },
530
- "required": ["elapsedTendTime"]
531
- }
532
- },
533
- {
534
- "if": {
535
- "properties": {
536
- "triggerStyle": {
537
- "const": "Price moves percentage of active range away"
538
- }
539
- }
540
- },
541
- "then": {
542
- "properties": {
543
- "percentageOfPositionRangeToTrigger": {
544
- "type": "number",
545
- "title": "Percentage of Range",
546
- "description": "The percentage of the range away to trigger new positions, 100% or 1 would be at the bounds of the range",
547
- "detailedDescription": "If you have a simple position ranging from ticks 0 - 100, and you set this value to 1, the trigger range will be the outer bounds. Using 0.5 would make the trigger range 25-75, 2 would make the range -50 - 150."
548
- },
549
- "elapsedTendTime": {
550
- "type": "number",
551
- "title": "Max time between tends",
552
- "description": "If trigger conditions have not been met for this period of time, the strategy will execute regardless of trigger logic to update vault accounting.",
553
- "default": 1209600
554
- }
555
- },
556
- "required": ["percentageOfPositionRangeToTrigger", "elapsedTendTime"]
557
- }
558
- },
559
- {
560
- "if": {
561
- "properties": {
562
- "triggerStyle": {
563
- "const": "Price moves one way past positions"
564
- }
565
- }
566
- },
567
- "then": {
568
- "properties": {
569
- "triggerWhenOver": {
570
- "type": "boolean",
571
- "title": "Price Moves Higher",
572
- "description": "True for if the strategy should set new positions when the price (tick) is higher than the current positions, false for lower",
573
- "detailedDescription": "If our current position ranges from ticks 0 - 100, true will make our bundle execute only when the current tick is higher. Any other case (current tick less than 100) will result in a continue recommendation."
574
- },
575
- "elapsedTendTime": {
576
- "type": "number",
577
- "title": "Max time between tends",
578
- "description": "If trigger conditions have not been met for this period of time, the strategy will execute regardless of trigger logic to update vault accounting.",
579
- "default": 1209600
580
- }
581
- },
582
- "required": ["triggerWhenOver", "elapsedTendTime"]
583
- }
584
- }`;
585
- }
@@ -1,39 +0,0 @@
1
- import { JSON } from 'json-as/assembly';
2
-
3
- @serializable
4
- export class Candle {
5
- timestamp: i64 = 0;
6
- high: f64 = 0.0;
7
- low: f64 = 0.0;
8
- open: f64 = 0.0;
9
- close: f64 = 0.0;
10
- volume: f64 = 0.0;
11
-
12
- constructor(timestamp: i64, high: f64, low: f64, open: f64, close: f64, volume: f64) {
13
- this.timestamp = timestamp;
14
- this.high = high;
15
- this.low = low;
16
- this.open = open;
17
- this.close = close;
18
- this.volume = volume;
19
- }
20
-
21
- toString(): string {
22
- return JSON.stringify(this);
23
- }
24
- }
25
-
26
- /**
27
- *
28
- * @param _data data connector data array
29
- * @returns
30
- */
31
- export function parsePrices(_data: string): Array<Candle> {
32
- return parseCandles(_data);
33
- }
34
-
35
- export function parseCandles(_data: string): Array<Candle> {
36
- // Parse an object using the JSON object
37
- let parsed: Array<Candle> = JSON.parse<Array<Candle>>(_data);
38
- return parsed;
39
- }
@@ -1,7 +0,0 @@
1
- import { JSON } from 'json-as/assembly';
2
- import { ExecutionContext } from "./ExecutionContext";
3
-
4
- @serializable
5
- export class DataConnectorConfig {
6
- executionContext: ExecutionContext = new ExecutionContext();
7
- }
@@ -1,11 +0,0 @@
1
- import { JSON } from 'json-as/assembly';
2
-
3
- @serializable
4
- export class ExecutionContext {
5
- executionTimestamp: number = 0;
6
- epochLength: number = 0;
7
- epochTimestamp: i32 = 0;
8
- vaultAddress: string = "";
9
- blockTime: i32 = 0;
10
- blockNumber: i32 = 0;
11
- }
@@ -1,14 +0,0 @@
1
- import { JSON } from 'json-as/assembly';
2
-
3
- @serializable
4
- export class RawTradeData {
5
- timestamp: i32 = 0;
6
- price: f64 = 0.0;
7
- volume: f64 = 0.0;
8
-
9
- constructor(timestamp: i32, price: f64, volume: f64) {
10
- this.timestamp = timestamp;
11
- this.price = price;
12
- this.volume = volume;
13
- }
14
- }
package/index.html DELETED
@@ -1,10 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <script type="module">
5
- import { initialize, execute } from "./build/release.js";
6
- document.body.innerText = 'Implementation missing, please fix index.html';;
7
- </script>
8
- </head>
9
- <body></body>
10
- </html>