@steerprotocol/strategy-utils 2.2.1 → 3.0.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.
- package/.github/workflows/nodejs.yml +9 -9
- package/CHANGELOG.md +28 -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/triggers.ts +469 -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/.vscode/settings.json +0 -8
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
import { JSON } from "json-as";
|
|
2
|
+
import { Position } from "./types";
|
|
3
|
+
|
|
4
|
+
// NOTE: Trigger functions return true when action should be taken, if false then the strategy can return 'continue' to skip exeuction
|
|
5
|
+
// Implementation might look like the following:
|
|
6
|
+
// const trigger = getTriggerStyle(configJson.triggerStyle)
|
|
7
|
+
// const triggerObj = new TriggerConfigHelper(configJson.triggerWhenOver, configJson.tickPriceTrigger, configJson.percentageOfPositionRangeToTrigger, configJson.tickDistanceFromCenter, configJson.elapsedTendTime)
|
|
8
|
+
// if (!shouldTriggerExecution(trigger, triggerObj, _positions, _currentTick, _timeSinceLastExecution)) return 'continue'
|
|
9
|
+
|
|
10
|
+
// Gets active range from the output of LM.getPositions()
|
|
11
|
+
export function parseActiveRange(_positions: string): Position {
|
|
12
|
+
// _positions will be '[[#,#,#],[#,#,#],[#,#,#]]' presumably. lower, upper, weight
|
|
13
|
+
// clean up our list by removing spaces and brackets
|
|
14
|
+
let positions = _positions.replaceAll(' ','');
|
|
15
|
+
positions = positions.replaceAll('[','');
|
|
16
|
+
let rangeArray = positions.split(']',2);
|
|
17
|
+
let startTick = rangeArray[0].split(',')[0];
|
|
18
|
+
let endRange = rangeArray[1].split(']',2);
|
|
19
|
+
const endTicks = endRange[0].split(',');
|
|
20
|
+
let endTick = endTicks[endTicks.length-1]
|
|
21
|
+
// if trailing comma
|
|
22
|
+
if (endTick == '') endTick = endTicks[endTicks.length-2]
|
|
23
|
+
const strArrays = [startTick, endTick];
|
|
24
|
+
// check null
|
|
25
|
+
if (strArrays[0] == '' || strArrays[0] == null || strArrays[1] == '' || strArrays[1] == null) {
|
|
26
|
+
return new Position(0, 0, 0);
|
|
27
|
+
}
|
|
28
|
+
// else return normal
|
|
29
|
+
const lowerTick = i32(parseInt(strArrays[0]));
|
|
30
|
+
const upperTick = i32(parseInt(strArrays[1]));
|
|
31
|
+
// weights shouldn't matter in this context, we just want the total active range
|
|
32
|
+
return new Position(lowerTick, upperTick, 100);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function emptyCurrentPosition(currentPosition: Position): boolean {
|
|
36
|
+
// return true if current position ticks are not the same
|
|
37
|
+
return currentPosition.startTick == currentPosition.endTick
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// where rebalance width is how far off on either side the trigger should activate
|
|
41
|
+
export function triggerFromDistance(currentPosition: Position, rebalanceWidth: i64, currentTick: i64): boolean {
|
|
42
|
+
if (emptyCurrentPosition(currentPosition)) return true
|
|
43
|
+
const centerPosition = (currentPosition.endTick + currentPosition.startTick) / 2
|
|
44
|
+
const upperTrigger = centerPosition + (rebalanceWidth)
|
|
45
|
+
const lowerTrigger = centerPosition - (rebalanceWidth)
|
|
46
|
+
// In bounds? return false to continue (skip exec), returns true to execute
|
|
47
|
+
return !((currentTick <= upperTrigger && currentTick >= lowerTrigger))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// tick moves % away from center of position range
|
|
51
|
+
export function triggerFromPercentage(currentPosition: Position, rebalancePercentage: f64, currentTick: i64): boolean {
|
|
52
|
+
if (emptyCurrentPosition(currentPosition)) return true
|
|
53
|
+
const side = (currentPosition.endTick - currentPosition.startTick) / 2
|
|
54
|
+
const centerPosition = (currentPosition.endTick + currentPosition.startTick) / 2
|
|
55
|
+
const triggerDiff = i64(Math.round(f64(side) * rebalancePercentage))
|
|
56
|
+
const upperTrigger = centerPosition + triggerDiff
|
|
57
|
+
const lowerTrigger = centerPosition - triggerDiff
|
|
58
|
+
// In bounds? return false to continue (skip exec), returns true to execute
|
|
59
|
+
return !((currentTick <= upperTrigger && currentTick >= lowerTrigger))
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// when current tick is no longer in the current position range
|
|
63
|
+
export function triggerPositionsInactive(currentPosition: Position, currentTick: i64): boolean {
|
|
64
|
+
// return JSON.stringify(currentPosition)
|
|
65
|
+
if (emptyCurrentPosition(currentPosition)) return true
|
|
66
|
+
|
|
67
|
+
return (!((currentTick <= currentPosition.endTick && currentTick >= currentPosition.startTick)))
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// when tick goes over or under specified tick, trigger rebalance
|
|
71
|
+
// export function triggerFromSpecifiedPrice(triggerTick: i64, currentTick: i64, triggerOver: boolean): boolean {
|
|
72
|
+
// // if trigger over, return true when currentTick > triggerTick
|
|
73
|
+
// if (triggerOver) {
|
|
74
|
+
// return currentTick > triggerTick
|
|
75
|
+
// }
|
|
76
|
+
// // trigger under, if current price is less than trigger tick return true
|
|
77
|
+
// return triggerTick > currentTick
|
|
78
|
+
// }
|
|
79
|
+
|
|
80
|
+
// when tick goes over or under current positions, trigger rebalance, only moves one way
|
|
81
|
+
export function triggerPricePastPositions(currentPosition: Position, currentTick: i64, triggerOver: boolean): boolean {
|
|
82
|
+
if (emptyCurrentPosition(currentPosition)) return true
|
|
83
|
+
if (triggerOver) {
|
|
84
|
+
// if the currentTick is over the endTick, rebal
|
|
85
|
+
return currentTick > i64(currentPosition.endTick)
|
|
86
|
+
}
|
|
87
|
+
// if current tick is under start tick
|
|
88
|
+
return currentTick < i64(currentPosition.startTick)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export const enum TriggerStyle {
|
|
92
|
+
DistanceFromCenterOfPositions,
|
|
93
|
+
PercentageChangeFromPositionRange,
|
|
94
|
+
PositionsInactive,
|
|
95
|
+
// SpecificPrice,
|
|
96
|
+
PricePastPositions,
|
|
97
|
+
None,
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// export function TriggerStyleLookup(triggerStyle: TriggerStyle): string {
|
|
101
|
+
// switch (triggerStyle) {
|
|
102
|
+
// case TriggerStyle.DistanceFromCenterOfPositions:
|
|
103
|
+
// return "Distance from center of position(s)";
|
|
104
|
+
// case TriggerStyle.PercentageChangeFromPositionRange:
|
|
105
|
+
// return "Percentage of position(s)";
|
|
106
|
+
// case TriggerStyle.PositionsInactive:
|
|
107
|
+
// return "Positions Inactive";
|
|
108
|
+
// // case TriggerStyle.SpecificPrice:
|
|
109
|
+
// // return "Specific Price";
|
|
110
|
+
// case TriggerStyle.PricePastPositions:
|
|
111
|
+
// return "Price moved past position(s)";
|
|
112
|
+
// case TriggerStyle.None:
|
|
113
|
+
// return 'None'
|
|
114
|
+
|
|
115
|
+
// default:
|
|
116
|
+
// throw new Error(`Unknown trigger style: ${triggerStyle}`);
|
|
117
|
+
// }
|
|
118
|
+
// }
|
|
119
|
+
|
|
120
|
+
// export class DistanceFromCenterOfPositionsOptions {
|
|
121
|
+
// tickDistanceFromCenter: i64 = 0;
|
|
122
|
+
// requiredDataTypes: string[] = ['Liquidity Manager Positions', 'V3 Pool Current Tick'];
|
|
123
|
+
// }
|
|
124
|
+
|
|
125
|
+
// export class PercentageChangeFromPositionRangeOptions {
|
|
126
|
+
// percentageOfPositionRangeToTrigger: f64 = 0.0;
|
|
127
|
+
// requiredDataTypes: string[] = ['Liquidity Manager Positions', 'V3 Pool Current Tick'];
|
|
128
|
+
// }
|
|
129
|
+
|
|
130
|
+
// export class PositionsInactiveOptions {
|
|
131
|
+
// requiredDataTypes: string[] = ['Liquidity Manager Positions', 'V3 Pool Current Tick'];
|
|
132
|
+
// }
|
|
133
|
+
|
|
134
|
+
// export class SpecificPriceOptions {
|
|
135
|
+
// tickPriceTrigger: i64 = 0;
|
|
136
|
+
// triggerWhenOver: boolean = false;
|
|
137
|
+
// requiredDataTypes: string[] = ['V3 Pool Current Tick'];
|
|
138
|
+
// }
|
|
139
|
+
|
|
140
|
+
// export class PricePastPositionsOptions {
|
|
141
|
+
// triggerWhenOver: boolean = false;
|
|
142
|
+
// requiredDataTypes: string[] = ['Liquidity Manager Positions', 'V3 Pool Current Tick'];
|
|
143
|
+
// }
|
|
144
|
+
|
|
145
|
+
// @ts-ignore
|
|
146
|
+
@json
|
|
147
|
+
export class TriggerConfigHelper {
|
|
148
|
+
// triggerType: string = "Price leaves active range";
|
|
149
|
+
triggerWhenOver: boolean = false;
|
|
150
|
+
tickPriceTrigger: i64 = 0;
|
|
151
|
+
percentageOfPositionRangeToTrigger: f64 = 0.0;
|
|
152
|
+
tickDistanceFromCenter: i64 = 0;
|
|
153
|
+
elapsedTendTime: i64 = 0;
|
|
154
|
+
constructor( t: boolean, tpt: i64, poptrr:f64, tdfc: i64, ett: i64) {
|
|
155
|
+
if(t) this.triggerWhenOver = t
|
|
156
|
+
if(tpt) this.tickPriceTrigger = tpt
|
|
157
|
+
if(poptrr) this.percentageOfPositionRangeToTrigger = poptrr
|
|
158
|
+
if(tdfc) this.tickDistanceFromCenter = tdfc
|
|
159
|
+
if(ett) this.elapsedTendTime = ett
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function getTriggerExpectedDataTypes(triggerStyle: TriggerStyle): string[] {
|
|
164
|
+
// currently we use only this list
|
|
165
|
+
const typicalTypes = ["Liquidity Manager Positions", "V3 Pool Current Tick", "Time Since Last Execution"]
|
|
166
|
+
switch (triggerStyle) {
|
|
167
|
+
case TriggerStyle.DistanceFromCenterOfPositions:
|
|
168
|
+
return typicalTypes;
|
|
169
|
+
case TriggerStyle.PercentageChangeFromPositionRange:
|
|
170
|
+
return typicalTypes;
|
|
171
|
+
case TriggerStyle.PositionsInactive:
|
|
172
|
+
return typicalTypes;
|
|
173
|
+
// case TriggerStyle.SpecificPrice:
|
|
174
|
+
// return "Specific Price";
|
|
175
|
+
case TriggerStyle.PricePastPositions:
|
|
176
|
+
return typicalTypes;
|
|
177
|
+
case TriggerStyle.None:
|
|
178
|
+
// return no data connectors for none
|
|
179
|
+
return [];
|
|
180
|
+
|
|
181
|
+
default:
|
|
182
|
+
throw new Error(`Unknown trigger style: ${triggerStyle}`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
export function getExpectedDataTypes(strategyDataConnectors: string[], triggerStyle: string): string {
|
|
188
|
+
const style = getTriggerStyle(triggerStyle)
|
|
189
|
+
const triggerDatas = getTriggerExpectedDataTypes(style)
|
|
190
|
+
const dataList = strategyDataConnectors.concat(triggerDatas)
|
|
191
|
+
let completeList = '['
|
|
192
|
+
for (let i: i32 = 0; i < dataList.length; i++) {
|
|
193
|
+
completeList += (' \"' + dataList[i] + '\"')
|
|
194
|
+
if (i != dataList.length-1) completeList += ','
|
|
195
|
+
}
|
|
196
|
+
completeList += ']'
|
|
197
|
+
return completeList
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// no AS func overloading yet :(
|
|
201
|
+
// export function shouldTriggerExecution_1(triggerStyle: TriggerStyle, triggerOptions: TriggerConfigHelper, dataConnector1: string) : boolean {
|
|
202
|
+
// // parse options
|
|
203
|
+
// switch (triggerStyle) {
|
|
204
|
+
// case TriggerStyle.SpecificPrice:
|
|
205
|
+
// // parse current tick from dc1
|
|
206
|
+
// const currentTick = parseInt(dataConnector1)
|
|
207
|
+
// if (!currentTick) return true
|
|
208
|
+
// // tick and over
|
|
209
|
+
// return triggerFromSpecifiedPrice(triggerOptions.tickPriceTrigger, currentTick, triggerOptions.triggerWhenOver)
|
|
210
|
+
// default:
|
|
211
|
+
// return true
|
|
212
|
+
// }
|
|
213
|
+
// }
|
|
214
|
+
|
|
215
|
+
// currently implemented as :: ulm positions [0], current tick [1], time since last execution [2]
|
|
216
|
+
// as more types are added this logic path with be redone
|
|
217
|
+
export function shouldTriggerExecution(
|
|
218
|
+
_triggerStyle: string,
|
|
219
|
+
triggerOptions: TriggerConfigHelper,
|
|
220
|
+
dataConnector1: string,
|
|
221
|
+
dataConnector2: string,
|
|
222
|
+
dataConnector3: string) : boolean {
|
|
223
|
+
|
|
224
|
+
// possible dc inputs
|
|
225
|
+
let currentPositionRange: Position;
|
|
226
|
+
let currentTick: i64;
|
|
227
|
+
const triggerStyle = getTriggerStyle(_triggerStyle)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
let timeSinceLastExecution: i64;
|
|
232
|
+
|
|
233
|
+
switch (triggerStyle) {
|
|
234
|
+
case TriggerStyle.DistanceFromCenterOfPositions:
|
|
235
|
+
// parse ulm positions [0], current tick [1]
|
|
236
|
+
// @ts-ignore
|
|
237
|
+
timeSinceLastExecution = i64(parseInt(dataConnector3))
|
|
238
|
+
if (timeSinceLastExecution >= i64(triggerOptions.elapsedTendTime)) return true
|
|
239
|
+
currentPositionRange = parseActiveRange(dataConnector1)
|
|
240
|
+
currentTick = i64(parseInt(dataConnector2))
|
|
241
|
+
return triggerFromDistance(currentPositionRange, triggerOptions.tickDistanceFromCenter, currentTick)
|
|
242
|
+
|
|
243
|
+
case TriggerStyle.PercentageChangeFromPositionRange:
|
|
244
|
+
// parse ulm positions [0], current tick [1]
|
|
245
|
+
timeSinceLastExecution = i64(parseInt(dataConnector3))
|
|
246
|
+
if (timeSinceLastExecution >= i64(triggerOptions.elapsedTendTime)) return true
|
|
247
|
+
currentPositionRange= parseActiveRange(dataConnector1)
|
|
248
|
+
currentTick = i64(parseInt(dataConnector2))
|
|
249
|
+
return triggerFromPercentage(currentPositionRange, triggerOptions.percentageOfPositionRangeToTrigger, currentTick)
|
|
250
|
+
|
|
251
|
+
case TriggerStyle.PositionsInactive:
|
|
252
|
+
// parse ulm positions [0], current tick [1]
|
|
253
|
+
timeSinceLastExecution = i64(parseInt(dataConnector3))
|
|
254
|
+
if (timeSinceLastExecution >= i64(triggerOptions.elapsedTendTime)) return true
|
|
255
|
+
currentPositionRange = parseActiveRange(dataConnector1)
|
|
256
|
+
currentTick = i64(parseInt(dataConnector2))
|
|
257
|
+
return triggerPositionsInactive(currentPositionRange, currentTick)
|
|
258
|
+
|
|
259
|
+
case TriggerStyle.PricePastPositions:
|
|
260
|
+
// parse ulm positions [0], current tick [1]
|
|
261
|
+
timeSinceLastExecution = i64(parseInt(dataConnector3))
|
|
262
|
+
if (timeSinceLastExecution >= i64(triggerOptions.elapsedTendTime)) return true
|
|
263
|
+
currentPositionRange = parseActiveRange(dataConnector1)
|
|
264
|
+
currentTick = i64(parseInt(dataConnector2))
|
|
265
|
+
return triggerPricePastPositions(currentPositionRange, currentTick, triggerOptions.triggerWhenOver)
|
|
266
|
+
default:
|
|
267
|
+
return true
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export function getTriggerStyle(trigger: string): TriggerStyle {
|
|
272
|
+
if (trigger === 'Current Price set distance from center of positions') {
|
|
273
|
+
return TriggerStyle.DistanceFromCenterOfPositions;
|
|
274
|
+
} else if (trigger === 'Price leaves active range') {
|
|
275
|
+
return TriggerStyle.PositionsInactive;
|
|
276
|
+
} else if (trigger === 'Price moves percentage of active range away') {
|
|
277
|
+
return TriggerStyle.PercentageChangeFromPositionRange;
|
|
278
|
+
} else if (trigger === 'Price moves one way past positions') {
|
|
279
|
+
return TriggerStyle.PricePastPositions;
|
|
280
|
+
} else {
|
|
281
|
+
return TriggerStyle.None;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function getTriggerName(trigger: TriggerStyle): string {
|
|
286
|
+
if (trigger === TriggerStyle.DistanceFromCenterOfPositions) {
|
|
287
|
+
return 'Current Price set distance from center of positions';
|
|
288
|
+
} else if (trigger === TriggerStyle.PositionsInactive) {
|
|
289
|
+
return 'Price leaves active range';
|
|
290
|
+
} else if (trigger === TriggerStyle.PercentageChangeFromPositionRange) {
|
|
291
|
+
return 'Price moves percentage of active range away';
|
|
292
|
+
} else if (trigger === TriggerStyle.PricePastPositions) {
|
|
293
|
+
return 'Price moves one way past positions';
|
|
294
|
+
} else {
|
|
295
|
+
return 'None';
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
export function triggerPropertyHelper(omit: TriggerStyle[] = []): string {
|
|
301
|
+
const triggerList = [
|
|
302
|
+
TriggerStyle.DistanceFromCenterOfPositions,
|
|
303
|
+
TriggerStyle.None,
|
|
304
|
+
TriggerStyle.PercentageChangeFromPositionRange,
|
|
305
|
+
TriggerStyle.PositionsInactive,
|
|
306
|
+
TriggerStyle.PricePastPositions,
|
|
307
|
+
];
|
|
308
|
+
|
|
309
|
+
const filteredTriggers: string[] = [
|
|
310
|
+
'Current Price set distance from center of positions',
|
|
311
|
+
'Price leaves active range',
|
|
312
|
+
'Price moves percentage of active range away',
|
|
313
|
+
'Price moves one way past positions',
|
|
314
|
+
'None'
|
|
315
|
+
];
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
return `"triggerStyle": {
|
|
319
|
+
"enum": ${JSON.stringify(filteredTriggers)},
|
|
320
|
+
"title": "Logic to trigger new positions",
|
|
321
|
+
"type": "string",
|
|
322
|
+
"default": "None"
|
|
323
|
+
}`;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export function allOfTrigger(strategyDataConnectors: string[]): string {
|
|
327
|
+
return `{
|
|
328
|
+
"if": {
|
|
329
|
+
"properties": {
|
|
330
|
+
"triggerStyle": {
|
|
331
|
+
"const": "None"
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
"then": {
|
|
336
|
+
"properties": {
|
|
337
|
+
"expectedDataTypes": {
|
|
338
|
+
"const": ${getExpectedDataTypes(strategyDataConnectors, "None")},
|
|
339
|
+
"default": ${getExpectedDataTypes(strategyDataConnectors, "None")},
|
|
340
|
+
"hidden": true,
|
|
341
|
+
"type": "string"
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
"required": ["expectedDataTypes"]
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
"if": {
|
|
349
|
+
"properties": {
|
|
350
|
+
"triggerStyle": {
|
|
351
|
+
"const": "Current Price set distance from center of positions"
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
"then": {
|
|
356
|
+
"properties": {
|
|
357
|
+
"tickDistanceFromCenter": {
|
|
358
|
+
"type": "integer",
|
|
359
|
+
"title": "Tick Distance",
|
|
360
|
+
"description": "The number of ticks (basis points) from center price of positions to trigger setting new positions",
|
|
361
|
+
"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."
|
|
362
|
+
},
|
|
363
|
+
"expectedDataTypes": {
|
|
364
|
+
"const": ${getExpectedDataTypes(strategyDataConnectors, "Current Price set distance from center of positions")},
|
|
365
|
+
"default": ${getExpectedDataTypes(strategyDataConnectors, "Current Price set distance from center of positions")},
|
|
366
|
+
"hidden": true,
|
|
367
|
+
"type": "string"
|
|
368
|
+
},
|
|
369
|
+
"elapsedTendTime": {
|
|
370
|
+
"type": "number",
|
|
371
|
+
"title": "Max time between tends",
|
|
372
|
+
"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.",
|
|
373
|
+
"default": 1209600
|
|
374
|
+
}
|
|
375
|
+
},
|
|
376
|
+
"required": ["tickDistanceFromCenter", "expectedDataTypes", "elapsedTendTime"]
|
|
377
|
+
}
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
"if": {
|
|
381
|
+
"properties": {
|
|
382
|
+
"triggerStyle": {
|
|
383
|
+
"const": "Price leaves active range"
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
},
|
|
387
|
+
"then": {
|
|
388
|
+
"properties": {
|
|
389
|
+
"expectedDataTypes": {
|
|
390
|
+
"const": ${getExpectedDataTypes(strategyDataConnectors, "Price leaves active range")},
|
|
391
|
+
"default": ${getExpectedDataTypes(strategyDataConnectors, "Price leaves active range")},
|
|
392
|
+
"hidden": true,
|
|
393
|
+
"type": "string"
|
|
394
|
+
},
|
|
395
|
+
"elapsedTendTime": {
|
|
396
|
+
"type": "number",
|
|
397
|
+
"title": "Max time between tends",
|
|
398
|
+
"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.",
|
|
399
|
+
"default": 1209600
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
"required": ["expectedDataTypes", "elapsedTendTime"]
|
|
403
|
+
}
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
"if": {
|
|
407
|
+
"properties": {
|
|
408
|
+
"triggerStyle": {
|
|
409
|
+
"const": "Price moves percentage of active range away"
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
},
|
|
413
|
+
"then": {
|
|
414
|
+
"properties": {
|
|
415
|
+
"percentageOfPositionRangeToTrigger": {
|
|
416
|
+
"type": "number",
|
|
417
|
+
"title": "Percentage of Range",
|
|
418
|
+
"description": "The percentage of the range away to trigger new positions, 100% or 1 would be at the bounds of the range",
|
|
419
|
+
"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."
|
|
420
|
+
},
|
|
421
|
+
"expectedDataTypes": {
|
|
422
|
+
"const": ${getExpectedDataTypes(strategyDataConnectors, "Price moves percentage of active range away")},
|
|
423
|
+
"default": ${getExpectedDataTypes(strategyDataConnectors, "Price moves percentage of active range away")},
|
|
424
|
+
"hidden": true,
|
|
425
|
+
"type": "string"
|
|
426
|
+
},
|
|
427
|
+
"elapsedTendTime": {
|
|
428
|
+
"type": "number",
|
|
429
|
+
"title": "Max time between tends",
|
|
430
|
+
"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.",
|
|
431
|
+
"default": 1209600
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
"required": ["percentageOfPositionRangeToTrigger", "expectedDataTypes", "elapsedTendTime"]
|
|
435
|
+
}
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
"if": {
|
|
439
|
+
"properties": {
|
|
440
|
+
"triggerStyle": {
|
|
441
|
+
"const": "Price moves one way past positions"
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
},
|
|
445
|
+
"then": {
|
|
446
|
+
"properties": {
|
|
447
|
+
"triggerWhenOver": {
|
|
448
|
+
"type": "boolean",
|
|
449
|
+
"title": "Price Moves Higher",
|
|
450
|
+
"description": "True for if the strategy should set new positions when the price (tick) is higher than the current positions, false for lower",
|
|
451
|
+
"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."
|
|
452
|
+
},
|
|
453
|
+
"expectedDataTypes": {
|
|
454
|
+
"const": ${getExpectedDataTypes(strategyDataConnectors, "Price moves one way past positions")},
|
|
455
|
+
"default": ${getExpectedDataTypes(strategyDataConnectors, "Price moves one way past positions")},
|
|
456
|
+
"hidden": true,
|
|
457
|
+
"type": "string"
|
|
458
|
+
},
|
|
459
|
+
"elapsedTendTime": {
|
|
460
|
+
"type": "number",
|
|
461
|
+
"title": "Max time between tends",
|
|
462
|
+
"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.",
|
|
463
|
+
"default": 1209600
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
"required": ["triggerWhenOver", "expectedDataTypes", "elapsedTendTime"]
|
|
467
|
+
}
|
|
468
|
+
}`;
|
|
469
|
+
}
|
package/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
import * as AsBind from "as-bind/dist/as-bind.cjs.js";
|
|
1
|
+
// const fs = require("fs");
|
|
2
|
+
// import * as AsBind from "as-bind/dist/as-bind.cjs.js";
|
|
3
3
|
|
|
4
|
-
const imports = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
};
|
|
4
|
+
// const imports = {
|
|
5
|
+
// console: { // File which you are injecting
|
|
6
|
+
// log(strPtr) {
|
|
7
|
+
// console.log(strPtr)
|
|
8
|
+
// }
|
|
9
|
+
// }
|
|
10
|
+
// };
|
|
11
11
|
|
|
12
|
-
const asBindInstance = AsBind.instantiateSync(fs.readFileSync(__dirname + "/build/untouched.wasm"), imports)
|
|
12
|
+
// const asBindInstance = AsBind.instantiateSync(fs.readFileSync(__dirname + "/build/untouched.wasm"), imports)
|
|
13
13
|
|
|
14
|
-
module.exports = asBindInstance.exports;
|
|
14
|
+
// module.exports = asBindInstance.exports;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@steerprotocol/strategy-utils",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Strategy utilities library for Steer Protocol strategies",
|
|
5
5
|
"main": "assembly/index.ts",
|
|
6
6
|
"types": "assembly/index.ts",
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"docs": "typedoc --tsconfig ./tsconfig.json",
|
|
14
14
|
"strategy": "yarn asbuild && yarn test",
|
|
15
15
|
"semantic-release": "semantic-release",
|
|
16
|
-
"commit": "cz"
|
|
16
|
+
"commit": "cz",
|
|
17
|
+
"postinstall": "patch-package"
|
|
17
18
|
},
|
|
18
19
|
"author": "Derek Barrera <derekbarrera@gmail.com>",
|
|
19
20
|
"license": "ISC",
|
|
@@ -21,11 +22,13 @@
|
|
|
21
22
|
"@babel/preset-typescript": "^7.14.5",
|
|
22
23
|
"@semantic-release/changelog": "^5.0.1",
|
|
23
24
|
"@semantic-release/git": "^9.0.0",
|
|
25
|
+
"@steerprotocol/app-loader": "^0.2.2",
|
|
24
26
|
"@steerprotocol/base-strategy": "0.1.0",
|
|
25
27
|
"as-bignum": "^0.2.23",
|
|
26
28
|
"commitizen": "^4.2.4",
|
|
27
29
|
"conventional-changelog-conventionalcommits": "^4.6.0",
|
|
28
|
-
"json-as": "^0.5.
|
|
30
|
+
"json-as": "^0.5.43",
|
|
31
|
+
"patch-package": "^8.0.0",
|
|
29
32
|
"typescript": "^4.3.5",
|
|
30
33
|
"visitor-as": "^0.11.4"
|
|
31
34
|
},
|