@steerprotocol/strategy-utils 1.1.1 → 2.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/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ### [1.1.2-alpha.1](https://github.com/SteerProtocol/strategy-utils-assemblyscript/compare/v1.1.1...v1.1.2-alpha.1) (2022-08-15)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * :ambulance: Specific Index for parse prices ([0940640](https://github.com/SteerProtocol/strategy-utils-assemblyscript/commit/09406407c7cb12bca2585976f3269414d9be731b))
7
+
8
+ ### [1.1.1-alpha.1](https://github.com/SteerProtocol/strategy-utils-assemblyscript/compare/v1.1.0...v1.1.1-alpha.1) (2022-07-26)
9
+
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * **devops:** :bug: Fix tests ([a2bb4d6](https://github.com/SteerProtocol/strategy-utils-assemblyscript/commit/a2bb4d6bdc5e3dc8bbcf6be6f26c74b8167675a7))
15
+
1
16
  ## [1.1.0](https://github.com/SteerProtocol/strategy-utils-assemblyscript/compare/v1.0.0...v1.1.0) (2022-07-26)
2
17
 
3
18
 
@@ -1,6 +1,3 @@
1
-
2
-
3
- // WARNING: classes will initially be allocated 1 page of memory, you will likely need to add size or flatten these classes
4
1
  export class SMA {
5
2
  private readonly prices: f32[] = [];
6
3
  private interval: i32 = 0;
@@ -15,7 +12,6 @@ export class SMA {
15
12
  return this.result;
16
13
  }
17
14
 
18
-
19
15
  update(price: f32): void {
20
16
  this.prices.push(price);
21
17
 
@@ -26,11 +22,10 @@ export class SMA {
26
22
  if (this.prices.length === this.interval) {
27
23
  let result = f32(0);
28
24
  for (let priceIndex = 0; priceIndex < this.prices.length; priceIndex++) {
29
- result = result + this.prices[priceIndex]
25
+ result = result + this.prices[priceIndex];
30
26
  }
31
27
  this.result = result / f32(this.prices.length || 1);
32
28
  }
33
-
34
29
  }
35
30
  }
36
31
 
@@ -39,8 +34,7 @@ export class EMA {
39
34
  private interval: i32 = 0;
40
35
  private result: f32;
41
36
  private multiplier: i32;
42
- private prevEMA : f32
43
-
37
+ private prevEMA: f32;
44
38
 
45
39
  constructor(interval: i32, multiplier: i32) {
46
40
  this.interval = interval;
@@ -56,18 +50,17 @@ export class EMA {
56
50
 
57
51
  if (this.prices.length > this.interval) {
58
52
  this.prices.shift();
59
- } // remove oldest price
53
+ } // remove oldest price
60
54
 
61
55
  if (!this.prevEMA) {
62
56
  this.prevEMA = price;
63
57
  }
64
58
 
59
+ let p1 = price * (f32(this.multiplier) / (1 + f32(this.interval)));
60
+ let p2 =
61
+ this.prevEMA * (1 - f32(this.multiplier) / (1 + f32(this.interval)));
65
62
 
66
- let p1 = price * (f32(this.multiplier) / (1 + f32(this.interval)))
67
- let p2 = this.prevEMA * (1 - (f32(this.multiplier) / (1 + f32(this.interval))))
68
-
69
- this.result = f32(p1 + p2)
63
+ this.result = f32(p1 + p2);
70
64
  this.prevEMA = this.result;
71
-
72
65
  }
73
- }
66
+ }
@@ -1,14 +1,14 @@
1
- import { Price } from "./types/Price";
1
+ import { Candle } from "./types/Candle";
2
2
  import { getMax, _mean, _getMax } from "./Math";
3
3
 
4
- export function getAverageTrueRange(prices: Array<Price>, interval: i32): f32 {
4
+ export function getAverageTrueRange(candles: Array<Candle>, interval: i32): f32 {
5
5
  let rangeSum: f32 = 0;
6
- for (let i = 1; i < prices.length; i++) {
7
- const currentPrice = prices[i];
6
+ for (let i = 1; i < candles.length; i++) {
7
+ const currentPrice = candles[i];
8
8
 
9
9
  const currentHigh = currentPrice.high
10
10
  const currentLow = currentPrice.low
11
- const previousClose = prices[i - 1].close
11
+ const previousClose = candles[i - 1].close
12
12
 
13
13
  const range1 = Math.abs(currentHigh - previousClose);
14
14
  const range2 = Math.abs(currentLow - previousClose);
@@ -19,12 +19,12 @@ export function getAverageTrueRange(prices: Array<Price>, interval: i32): f32 {
19
19
  }
20
20
 
21
21
 
22
- return f32(rangeSum) / f32(prices.length - 1);
22
+ return f32(rangeSum) / f32(candles.length - 1);
23
23
 
24
24
  }
25
25
 
26
26
 
27
- export function trailingStop(percent: f32, prices: Price[]): f32 {
27
+ export function trailingStop(percent: f32, prices: Candle[]): f32 {
28
28
  // Get the current price of the asset pair
29
29
  const currentPrice = prices[prices.length - 1];
30
30
 
@@ -32,15 +32,15 @@ export function getAverageTrueRange(prices: Array<Price>, interval: i32): f32 {
32
32
  const trailingStopPrice = currentPrice.close - (currentPrice.close * f32(percent / 100));
33
33
 
34
34
  // Return the trailing stop price
35
- return trailingStopPrice;
35
+ return f32(trailingStopPrice);
36
36
  }
37
37
 
38
- export function trueRange(price: Price): f32{
39
- const trueRange = getMax(price.high - price.low,getMax(f32(Math.abs(price.high-price.close)),f32(Math.abs(price.low-price.close))));
38
+ export function trueRange(price: Candle): f32{
39
+ const trueRange = getMax(f32(price.high) - f32(price.low),getMax(f32(Math.abs(price.high-price.close)),f32(Math.abs(price.low-price.close))));
40
40
  return trueRange;
41
41
  }
42
42
 
43
- export function averageTrueRange(prices: Price[]): f32 {
43
+ export function averageTrueRange(prices: Candle[]): f32 {
44
44
  const trueRanges: f32[] = []
45
45
  for (let i = 0; i < prices.length; i++) {
46
46
  trueRanges.push(trueRange(prices[i]));
@@ -1,48 +1,60 @@
1
- import {Position } from "./types";
1
+ import { Position } from "./types";
2
2
 
3
- export function getTickSpacing(poolFee: i32): i32{
4
- let spacing = 0;
5
- switch (poolFee){
6
- case 100:
7
- spacing = 1;
8
- break;
9
- case 500:
10
- spacing = 10;
11
- break;
12
- case 3000:
13
- spacing = 60;
14
- break;
15
- default:
16
- spacing = 200;
17
- }
18
- return spacing;
3
+ export function getTickSpacing(poolFee: i32): i32 {
4
+ let spacing = 0;
5
+ switch (poolFee) {
6
+ case 100:
7
+ spacing = 1;
8
+ break;
9
+ case 500:
10
+ spacing = 10;
11
+ break;
12
+ case 3000:
13
+ spacing = 60;
14
+ break;
15
+ default:
16
+ spacing = 200;
17
+ }
18
+ return spacing;
19
19
  }
20
20
 
21
21
  // Function shaped for making positions with the UniLiquidityManager contract for ease
22
- export function renderULMResult(positions: Array<Position>): string {
22
+ export function renderULMResult(
23
+ positions: Array<Position>,
24
+ totalLiquidity1e4: number
25
+ ): string {
26
+ // Construct necessary object
27
+ const lowerTicks: Array<i32> = [];
28
+ const upperTicks: Array<i32> = [];
29
+ const weights: Array<i32> = [];
23
30
 
24
- // Construct necessary object
25
- const lowerTicks: Array<i32> = []
26
- const upperTicks: Array<i32> = []
27
- const weights: Array<i32> = []
31
+ for (let i = 0; i < positions.length; i++) {
32
+ lowerTicks.push(positions[i].startTick);
33
+ upperTicks.push(positions[i].endTick);
34
+ weights.push(positions[i].weight);
35
+ }
28
36
 
29
- for (let i = 0; i < positions.length; i++) {
30
- lowerTicks.push(positions[i].startTick)
31
- upperTicks.push(positions[i].endTick)
32
- weights.push(positions[i].weight)
33
- }
34
-
35
- return `{"functionName":"tend(uint256,(int24[],int24[],uint16[]),bytes)",
37
+ return (
38
+ `{"functionName":"tend(uint256,(int24[],int24[],uint16[]),bytes)",
36
39
  "typesArray":["uint256","tuple(int24[],int24[],uint16[])","bytes"],
37
- "valuesArray":[10000, [[`+lowerTicks.toString() +'],['+upperTicks.toString()+'],['+ weights.toString() +`]], "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000ffffffffffffffffffffffffffffffffffffffff"]
40
+ "valuesArray":[` +
41
+ totalLiquidity1e4.toString() +
42
+ `}, [[` +
43
+ lowerTicks.toString() +
44
+ "],[" +
45
+ upperTicks.toString() +
46
+ "],[" +
47
+ weights.toString() +
48
+ `]], "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000ffffffffffffffffffffffffffffffffffffffff"]
38
49
  }`
39
- // The bytes value here is a placeholder for encoding that gets replaced with time-sensitive data upon execution. It will actually be the swap amount for rebalancing (int256) and slippage limit (uint160)
50
+ );
51
+ // The bytes value here is a placeholder for encoding that gets replaced with time-sensitive data upon execution. It will actually be the swap amount for rebalancing (int256) and slippage limit (uint160)
40
52
  }
41
53
 
42
54
  // TODO: Might need to be rewritten for assets
43
55
  // Price must be in the native token
44
56
  // token0 for token1
45
57
  export function getTickFromPrice(price: f32): f32 {
46
- const tick = Math.log(price) / Math.log(f32(1.0001));
47
- return f32(tick);
48
- }
58
+ const tick = Math.log(price) / Math.log(f32(1.0001));
59
+ return f32(tick);
60
+ }
@@ -0,0 +1,41 @@
1
+ import * as JSON from '@serial-as/json'
2
+ import {console} from '../console'
3
+
4
+ @serializable
5
+ export class Candle{
6
+ timestamp: i64 = 0;
7
+ high: number = 0.0;
8
+ low: number = 0.0;
9
+ open: number = 0.0;
10
+ close: number = 0.0;
11
+
12
+ constructor(timestamp: i64, high: number, low: number, open: number, close: number) {
13
+ this.timestamp = timestamp;
14
+ this.high = high;
15
+ this.low = low;
16
+ this.open = open;
17
+ this.close = close;
18
+ }
19
+
20
+ toString(): string {
21
+ return JSON.stringify(this);
22
+ }
23
+ }
24
+
25
+ /**
26
+ *
27
+ * @param _data data connector data array
28
+ * @returns
29
+ */
30
+ export function parsePrices(_data: string): Array<Candle> {
31
+ return parseCandles(_data);
32
+ }
33
+
34
+ export function parseCandles(_data: string): Array<Candle> {
35
+ // Parse an object using the JSON object
36
+ let parsed: Array<Candle> = JSON.parse<Array<Candle>>(_data);
37
+
38
+ console.log('parsed: ' + parsed.toString())
39
+
40
+ return parsed;
41
+ }
@@ -1,2 +1,2 @@
1
1
  export * from './Position';
2
- export * from './Price';
2
+ export * from './Candle';
package/index.js CHANGED
@@ -9,6 +9,6 @@ const imports = {
9
9
  }
10
10
  };
11
11
 
12
- const asBindInstance = AsBind.instantiateSync(fs.readFileSync(__dirname + "/build/optimized.wasm"), imports)
12
+ const asBindInstance = AsBind.instantiateSync(fs.readFileSync(__dirname + "/build/untouched.wasm"), imports)
13
13
 
14
14
  module.exports = asBindInstance.exports;
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@steerprotocol/strategy-utils",
3
- "version": "1.1.1",
3
+ "version": "2.0.0",
4
4
  "description": "Strategy utilities library for Steer Protocol strategies",
5
5
  "main": "assembly/index.ts",
6
6
  "types": "assembly/index.ts",
7
7
  "scripts": {
8
8
  "test": "yarn jest",
9
- "asbuild:untouched": "asc assembly/index.ts --target debug --exportRuntime --transform as-bind",
10
- "asbuild:optimized": "asc assembly/index.ts --target release --exportRuntime --transform as-bind",
9
+ "asbuild:untouched": "asc assembly/index.ts --target debug --exportRuntime --transform as-bind --transform @serial-as/transform",
10
+ "asbuild:optimized": "asc assembly/index.ts --target release --exportRuntime --transform as-bind --transform @serial-as/transform",
11
11
  "asbuild": "npm run asbuild:untouched && npm run asbuild:optimized",
12
12
  "docs": "typedoc --tsconfig ./tsconfig.json",
13
13
  "strategy": "yarn asbuild && yarn test",
@@ -21,6 +21,7 @@
21
21
  "@babel/preset-typescript": "^7.14.5",
22
22
  "@semantic-release/changelog": "^5.0.1",
23
23
  "@semantic-release/git": "^9.0.0",
24
+ "@serial-as/json": "1.0.2",
24
25
  "@steerprotocol/base-strategy": "^0.0.2",
25
26
  "as-bind": "^0.8.0",
26
27
  "assemblyscript-json": "^1.1.0",
@@ -3,21 +3,26 @@ const myModule = require("../index");
3
3
  describe("WASM Module", () => {
4
4
  describe("keltnerChannels", () => {
5
5
  it("Price should ", async () => {
6
- const price = new myModule.Price(1,2,3,4);
6
+ const price = new myModule.Candle("123",1,2,3,4);
7
7
  expect(price.high).toBe(1);
8
8
  expect(price.low).toBe(2);
9
9
  expect(price.open).toBe(3);
10
10
  expect(price.close).toBe(4);
11
11
  });
12
12
  it("True average should compute properly", async () => {
13
- const prices = [new myModule.Price(1,2,3,4),new myModule.Price(2,3,4,5)];
13
+ const prices = [new myModule.Candle("12342343",1,2,3,4),new myModule.Candle("12342343",2,3,4,5)];
14
14
  const trueAverage = myModule.getAverageTrueRange(prices, 1);
15
15
  expect(trueAverage).toBe(2);
16
16
  });
17
17
  it("True average should support decimals ", async () => {
18
- const prices = [new myModule.Price(6.1,4.2,2.5,1.11),new myModule.Price(41,32,41,15)];
18
+ const prices = [new myModule.Candle("12342343",6.1,4.2,2.5,1.11),new myModule.Candle("12342343",41,32,41,15)];
19
19
  const trueAverage = myModule.getAverageTrueRange(prices, 1);
20
20
  expect(trueAverage).toBe(39.88999938964844)
21
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
+ });
22
27
  });
23
28
  });
@@ -1,60 +0,0 @@
1
- import { JSON } from "assemblyscript-json";
2
-
3
- export class Price {
4
- constructor(
5
- public high: f32,
6
- public low: f32,
7
- public open: f32,
8
- public close: f32
9
- ) {}
10
- }
11
-
12
- export function parsePrices(_prices: String): Array<Price> {
13
- const prices = _prices;
14
- // Parse an object using the JSON object
15
- let jsonObj: JSON.Obj = <JSON.Obj>JSON.parse(prices);
16
- const result: Array<Price> = [];
17
-
18
- const data_arr = <JSON.Arr>jsonObj.getArr("data");
19
- if (data_arr == null) {throw new Error()};
20
- // First and only data result for this strategy is the candles
21
- const val = <JSON.Arr>data_arr._arr[0]
22
- if (val != null) {
23
- if (val.isArr) {
24
- const pricesArray = (<JSON.Arr>val).valueOf();
25
-
26
- for (let priceIndex = 0; priceIndex < pricesArray.length; priceIndex++) {
27
- const price = pricesArray[priceIndex];
28
-
29
- const candle = <JSON.Obj>JSON.parse(price.toString());
30
-
31
- if (candle.isObj) {
32
- const cl = candle.getValue("close");
33
- const hi = candle.getValue("high");
34
- const lo = candle.getValue("low");
35
- const op = candle.getValue("open");
36
-
37
- if (cl && hi && lo && op) {
38
- //@ts-ignore
39
- const close = f32(Number.parseFloat(cl.toString()));
40
- //@ts-ignore
41
- const high = f32(Number.parseFloat(hi.toString()));
42
- //@ts-ignore
43
- const low = f32(Number.parseFloat(lo.toString()));
44
- //@ts-ignore
45
- const open = f32(Number.parseFloat(op.toString()));
46
-
47
- const obj: Price = new Price(high, low, open, close);
48
-
49
- result.push(obj);
50
- }
51
- }
52
-
53
- return result;
54
- }
55
- }
56
- return [];
57
- } else {
58
- return [];
59
- }
60
- }