@pear-protocol/market-sdk 0.0.12 → 0.0.14
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/dist/chart/cache/index.js +15 -3
- package/dist/chart/chart.js +14 -23
- package/dist/chart/collector/binance.js +4 -0
- package/dist/chart/collector/bybit.js +12 -1
- package/dist/chart/collector/helpers.js +3 -0
- package/dist/chart/collector/hyperliquid.js +12 -2
- package/dist/chart/collector/index.js +27 -12
- package/dist/chart/collector/lighter.js +4 -2
- package/dist/chart/collector/okx.js +12 -1
- package/dist/chart/compute/asset.js +4 -0
- package/dist/chart/compute/performance.js +20 -4
- package/dist/chart/compute/price-ratio.js +8 -1
- package/dist/chart/compute/weighted-ratio.js +9 -1
- package/dist/chart/utils.js +19 -11
- package/dist/chart/ws/base-candle.d.ts +11 -5
- package/dist/chart/ws/base-candle.js +6 -2
- package/dist/chart/ws/binance.d.ts +4 -6
- package/dist/chart/ws/binance.js +33 -19
- package/dist/chart/ws/bybit.d.ts +4 -6
- package/dist/chart/ws/bybit.js +40 -24
- package/dist/chart/ws/hyperliquid.d.ts +4 -6
- package/dist/chart/ws/hyperliquid.js +37 -19
- package/dist/chart/ws/index.js +3 -0
- package/dist/chart/ws/lighter.d.ts +20 -20
- package/dist/chart/ws/lighter.js +75 -196
- package/dist/chart/ws/okx.d.ts +4 -6
- package/dist/chart/ws/okx.js +47 -23
- package/dist/funding-rate/fetcher/binance.js +7 -1
- package/dist/funding-rate/fetcher/bybit.js +15 -13
- package/dist/funding-rate/fetcher/http-client.js +11 -8
- package/dist/funding-rate/fetcher/hyperliquid.js +7 -1
- package/dist/funding-rate/fetcher/index.js +3 -0
- package/dist/funding-rate/fetcher/lighter.js +7 -1
- package/dist/funding-rate/fetcher/okx.js +14 -12
- package/dist/funding-rate/funding-rate.js +29 -21
- package/dist/funding-rate/utils.js +26 -5
- package/dist/orderbook/book/aggregate.js +16 -3
- package/dist/orderbook/book/local-book.js +16 -5
- package/dist/orderbook/orderbook.js +29 -13
- package/dist/orderbook/types.js +7 -1
- package/dist/orderbook/utils.js +5 -0
- package/dist/orderbook/ws/base-depth.js +10 -1
- package/dist/orderbook/ws/binance.js +28 -7
- package/dist/orderbook/ws/bybit.js +20 -5
- package/dist/orderbook/ws/hyperliquid.js +31 -11
- package/dist/orderbook/ws/index.js +3 -0
- package/dist/orderbook/ws/lighter.js +22 -7
- package/dist/orderbook/ws/okx.js +23 -2
- package/dist/transport/base-transport.js +5 -0
- package/dist/transport/binance.js +5 -0
- package/dist/transport/bybit.js +8 -1
- package/dist/transport/hyperliquid.js +8 -1
- package/dist/transport/index.js +3 -0
- package/dist/transport/lighter.js +8 -1
- package/dist/transport/okx.js +5 -0
- package/package.json +2 -2
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { createKey, mergeRanges, getIntervalSeconds } from '../utils';
|
|
2
2
|
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
5
|
class CandleCache {
|
|
6
|
+
static {
|
|
7
|
+
__name(this, "CandleCache");
|
|
8
|
+
}
|
|
4
9
|
historicalPriceData = {};
|
|
5
10
|
loadingTokens = /* @__PURE__ */ new Set();
|
|
6
11
|
addLoadingToken(symbol) {
|
|
@@ -13,7 +18,9 @@ class CandleCache {
|
|
|
13
18
|
const key = createKey(symbol, interval);
|
|
14
19
|
const existing = this.historicalPriceData[key];
|
|
15
20
|
if (!existing) {
|
|
16
|
-
const sortedCandles = [
|
|
21
|
+
const sortedCandles = [
|
|
22
|
+
...candles
|
|
23
|
+
].sort((a, b) => a.t - b.t);
|
|
17
24
|
const noDataBefore2 = sortedCandles.length === 0 ? range.end : null;
|
|
18
25
|
this.historicalPriceData[key] = {
|
|
19
26
|
symbol,
|
|
@@ -21,14 +28,19 @@ class CandleCache {
|
|
|
21
28
|
candles: sortedCandles,
|
|
22
29
|
oldestTime: sortedCandles.length > 0 ? sortedCandles[0]?.t ?? null : null,
|
|
23
30
|
latestTime: sortedCandles.length > 0 ? sortedCandles[sortedCandles.length - 1]?.t ?? null : null,
|
|
24
|
-
requestedRanges: [
|
|
31
|
+
requestedRanges: [
|
|
32
|
+
range
|
|
33
|
+
],
|
|
25
34
|
noDataBefore: noDataBefore2
|
|
26
35
|
};
|
|
27
36
|
return;
|
|
28
37
|
}
|
|
29
38
|
const existingTimes = new Set(existing.candles.map((c) => c.t));
|
|
30
39
|
const newCandles = candles.filter((c) => !existingTimes.has(c.t));
|
|
31
|
-
const mergedCandles = [
|
|
40
|
+
const mergedCandles = [
|
|
41
|
+
...existing.candles,
|
|
42
|
+
...newCandles
|
|
43
|
+
].sort((a, b) => a.t - b.t);
|
|
32
44
|
const oldestTime = mergedCandles.length > 0 ? mergedCandles[0]?.t ?? null : null;
|
|
33
45
|
const latestTime = mergedCandles.length > 0 ? mergedCandles[mergedCandles.length - 1]?.t ?? null : null;
|
|
34
46
|
const mergedRanges = mergeRanges(existing.requestedRanges, range);
|
package/dist/chart/chart.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { DataCollector } from './collector';
|
|
2
2
|
import { computePerformanceCandles, computePriceRatioCandles, computeWeightedRatioCandles, computeAssetBars, computeRealtimePerformanceBar, computeRealtimePriceRatioBar, computeRealtimeWeightedRatioBar, computeRealtimeAssetBar } from './compute/index';
|
|
3
3
|
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
6
|
class Chart {
|
|
7
|
+
static {
|
|
8
|
+
__name(this, "Chart");
|
|
9
|
+
}
|
|
5
10
|
collector;
|
|
6
11
|
baselinePrices = {};
|
|
7
12
|
constructor(config) {
|
|
@@ -20,21 +25,13 @@ class Chart {
|
|
|
20
25
|
const tokenCandles = await this.collector.fetchHistoricalPriceData(startTime, endTime, interval);
|
|
21
26
|
switch (chartType) {
|
|
22
27
|
case "weighted-ratio": {
|
|
23
|
-
return computeWeightedRatioCandles(
|
|
24
|
-
this.collector.getLongTokens(),
|
|
25
|
-
this.collector.getShortTokens(),
|
|
26
|
-
tokenCandles
|
|
27
|
-
);
|
|
28
|
+
return computeWeightedRatioCandles(this.collector.getLongTokens(), this.collector.getShortTokens(), tokenCandles);
|
|
28
29
|
}
|
|
29
30
|
case "price-ratio": {
|
|
30
31
|
return computePriceRatioCandles(this.collector.getLongTokens(), this.collector.getShortTokens(), tokenCandles);
|
|
31
32
|
}
|
|
32
33
|
case "performance": {
|
|
33
|
-
const result = computePerformanceCandles(
|
|
34
|
-
this.collector.getLongTokens(),
|
|
35
|
-
this.collector.getShortTokens(),
|
|
36
|
-
tokenCandles
|
|
37
|
-
);
|
|
34
|
+
const result = computePerformanceCandles(this.collector.getLongTokens(), this.collector.getShortTokens(), tokenCandles);
|
|
38
35
|
if (result.bars.length > 0) {
|
|
39
36
|
this.baselinePrices = result.baselinePrices;
|
|
40
37
|
}
|
|
@@ -57,7 +54,7 @@ class Chart {
|
|
|
57
54
|
if (!this.collector.isWsAttached) {
|
|
58
55
|
this.collector.attachCandleWs();
|
|
59
56
|
}
|
|
60
|
-
const formatTokens = (tokens) => tokens.map((t) => `${t.symbol}:${t.weight}`).join(",");
|
|
57
|
+
const formatTokens = /* @__PURE__ */ __name((tokens) => tokens.map((t) => `${t.symbol}:${t.weight}`).join(","), "formatTokens");
|
|
61
58
|
const id = `${chartType}-${formatTokens(this.collector.getLongTokens())}-${formatTokens(this.collector.getShortTokens())}`;
|
|
62
59
|
this.collector.addRealtimeListener(id, () => {
|
|
63
60
|
const snapshot = this.collector.getLatestCandles();
|
|
@@ -65,23 +62,14 @@ class Chart {
|
|
|
65
62
|
let bar = null;
|
|
66
63
|
switch (chartType) {
|
|
67
64
|
case "weighted-ratio":
|
|
68
|
-
bar = computeRealtimeWeightedRatioBar(
|
|
69
|
-
this.collector.getLongTokens(),
|
|
70
|
-
this.collector.getShortTokens(),
|
|
71
|
-
snapshot
|
|
72
|
-
);
|
|
65
|
+
bar = computeRealtimeWeightedRatioBar(this.collector.getLongTokens(), this.collector.getShortTokens(), snapshot);
|
|
73
66
|
break;
|
|
74
67
|
case "price-ratio":
|
|
75
68
|
bar = computeRealtimePriceRatioBar(this.collector.getLongTokens(), this.collector.getShortTokens(), snapshot);
|
|
76
69
|
break;
|
|
77
70
|
case "performance":
|
|
78
71
|
if (Object.keys(this.baselinePrices).length === 0) break;
|
|
79
|
-
bar = computeRealtimePerformanceBar(
|
|
80
|
-
this.collector.getLongTokens(),
|
|
81
|
-
this.collector.getShortTokens(),
|
|
82
|
-
snapshot,
|
|
83
|
-
this.baselinePrices
|
|
84
|
-
);
|
|
72
|
+
bar = computeRealtimePerformanceBar(this.collector.getLongTokens(), this.collector.getShortTokens(), snapshot, this.baselinePrices);
|
|
85
73
|
break;
|
|
86
74
|
}
|
|
87
75
|
if (bar) {
|
|
@@ -124,7 +112,10 @@ class Chart {
|
|
|
124
112
|
this.collector.removeRealtimeListener(id);
|
|
125
113
|
}
|
|
126
114
|
assertTokenExists(symbol) {
|
|
127
|
-
const allTokens = [
|
|
115
|
+
const allTokens = [
|
|
116
|
+
...this.collector.getLongTokens(),
|
|
117
|
+
...this.collector.getShortTokens()
|
|
118
|
+
];
|
|
128
119
|
if (!allTokens.some((t) => t.symbol === symbol)) {
|
|
129
120
|
throw new Error(`Symbol "${symbol}" is not part of the configured long or short tokens`);
|
|
130
121
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
1
3
|
const BINANCE_FUTURES_URL = "https://fapi.binance.com/fapi/v1/klines";
|
|
2
4
|
const MAX_LIMIT = 1e3;
|
|
3
5
|
function toCandleData(kline) {
|
|
@@ -10,6 +12,7 @@ function toCandleData(kline) {
|
|
|
10
12
|
c: Number(kline[4])
|
|
11
13
|
};
|
|
12
14
|
}
|
|
15
|
+
__name(toCandleData, "toCandleData");
|
|
13
16
|
async function fetchHistoricalCandles(symbol, startTime, endTime, interval) {
|
|
14
17
|
const params = new URLSearchParams({
|
|
15
18
|
symbol,
|
|
@@ -23,5 +26,6 @@ async function fetchHistoricalCandles(symbol, startTime, endTime, interval) {
|
|
|
23
26
|
const data = await response.json();
|
|
24
27
|
return data.map(toCandleData);
|
|
25
28
|
}
|
|
29
|
+
__name(fetchHistoricalCandles, "fetchHistoricalCandles");
|
|
26
30
|
|
|
27
31
|
export { fetchHistoricalCandles };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
1
3
|
const BYBIT_URL = "https://api.bybit.com/v5/market/kline";
|
|
2
4
|
const MAX_LIMIT = 1e3;
|
|
3
5
|
const intervalMap = {
|
|
@@ -18,8 +20,16 @@ const intervalMap = {
|
|
|
18
20
|
};
|
|
19
21
|
function toCandleData(item) {
|
|
20
22
|
const startMs = Number(item[0]);
|
|
21
|
-
return {
|
|
23
|
+
return {
|
|
24
|
+
t: startMs,
|
|
25
|
+
T: startMs,
|
|
26
|
+
o: Number(item[1]),
|
|
27
|
+
h: Number(item[2]),
|
|
28
|
+
l: Number(item[3]),
|
|
29
|
+
c: Number(item[4])
|
|
30
|
+
};
|
|
22
31
|
}
|
|
32
|
+
__name(toCandleData, "toCandleData");
|
|
23
33
|
async function fetchHistoricalCandles(symbol, startTime, endTime, interval) {
|
|
24
34
|
const params = new URLSearchParams({
|
|
25
35
|
category: "linear",
|
|
@@ -35,5 +45,6 @@ async function fetchHistoricalCandles(symbol, startTime, endTime, interval) {
|
|
|
35
45
|
if (data.retCode !== 0) throw new Error(`Bybit API error: ${data.retMsg}`);
|
|
36
46
|
return data.result.list.reverse().map((item) => toCandleData(item));
|
|
37
47
|
}
|
|
48
|
+
__name(fetchHistoricalCandles, "fetchHistoricalCandles");
|
|
38
49
|
|
|
39
50
|
export { fetchHistoricalCandles };
|
|
@@ -4,6 +4,8 @@ import { fetchHistoricalCandles as fetchHistoricalCandles$5 } from './hyperliqui
|
|
|
4
4
|
import { fetchHistoricalCandles as fetchHistoricalCandles$1 } from './lighter';
|
|
5
5
|
import { fetchHistoricalCandles as fetchHistoricalCandles$2 } from './okx';
|
|
6
6
|
|
|
7
|
+
var __defProp = Object.defineProperty;
|
|
8
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
7
9
|
async function fetchHistoricalCandles(connector, symbol, startTime, endTime, interval) {
|
|
8
10
|
switch (connector) {
|
|
9
11
|
case "hyperliquid":
|
|
@@ -20,5 +22,6 @@ async function fetchHistoricalCandles(connector, symbol, startTime, endTime, int
|
|
|
20
22
|
throw new Error(`Unsupported connector: ${connector}`);
|
|
21
23
|
}
|
|
22
24
|
}
|
|
25
|
+
__name(fetchHistoricalCandles, "fetchHistoricalCandles");
|
|
23
26
|
|
|
24
27
|
export { fetchHistoricalCandles };
|
|
@@ -1,15 +1,25 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
1
3
|
async function fetchHistoricalCandles(symbol, startTime, endTime, interval) {
|
|
2
4
|
const request = {
|
|
3
|
-
req: {
|
|
5
|
+
req: {
|
|
6
|
+
coin: symbol,
|
|
7
|
+
startTime,
|
|
8
|
+
endTime,
|
|
9
|
+
interval
|
|
10
|
+
},
|
|
4
11
|
type: "candleSnapshot"
|
|
5
12
|
};
|
|
6
13
|
const response = await fetch("https://api.hyperliquid.xyz/info", {
|
|
7
14
|
method: "POST",
|
|
8
|
-
headers: {
|
|
15
|
+
headers: {
|
|
16
|
+
"Content-Type": "application/json"
|
|
17
|
+
},
|
|
9
18
|
body: JSON.stringify(request)
|
|
10
19
|
});
|
|
11
20
|
if (!response.ok) throw new Error(`Hyperliquid API error: ${response.status} ${response.statusText}`);
|
|
12
21
|
return response.json();
|
|
13
22
|
}
|
|
23
|
+
__name(fetchHistoricalCandles, "fetchHistoricalCandles");
|
|
14
24
|
|
|
15
25
|
export { fetchHistoricalCandles };
|
|
@@ -2,7 +2,12 @@ import { CandleCache } from '../cache';
|
|
|
2
2
|
import { createCandleWs } from '../ws';
|
|
3
3
|
import { fetchHistoricalCandles } from './helpers';
|
|
4
4
|
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
5
7
|
class DataCollector {
|
|
8
|
+
static {
|
|
9
|
+
__name(this, "DataCollector");
|
|
10
|
+
}
|
|
6
11
|
transport;
|
|
7
12
|
longTokens;
|
|
8
13
|
shortTokens;
|
|
@@ -56,7 +61,9 @@ class DataCollector {
|
|
|
56
61
|
for (const token of this.getAllTokens()) {
|
|
57
62
|
const latestCandle = this.cache.getLatestCandle(token.symbol, this.candleInterval);
|
|
58
63
|
if (latestCandle) {
|
|
59
|
-
this.candleWs.onHistoricalDataFetched(token.symbol, this.candleInterval, [
|
|
64
|
+
this.candleWs.onHistoricalDataFetched(token.symbol, this.candleInterval, [
|
|
65
|
+
latestCandle
|
|
66
|
+
]);
|
|
60
67
|
}
|
|
61
68
|
this.candleWs.subscribe(token.symbol, this.candleInterval);
|
|
62
69
|
}
|
|
@@ -123,19 +130,24 @@ class DataCollector {
|
|
|
123
130
|
try {
|
|
124
131
|
const fetchPromises = tokensToFetch.map(async (token) => {
|
|
125
132
|
try {
|
|
126
|
-
const candles = await fetchHistoricalCandles(
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
interval
|
|
132
|
-
);
|
|
133
|
-
this.cache.addHistoricalPriceData(token.symbol, interval, candles, { start: startTime, end: endTime });
|
|
133
|
+
const candles = await fetchHistoricalCandles(this.transport.connector, token.symbol, startTime, endTime, interval);
|
|
134
|
+
this.cache.addHistoricalPriceData(token.symbol, interval, candles, {
|
|
135
|
+
start: startTime,
|
|
136
|
+
end: endTime
|
|
137
|
+
});
|
|
134
138
|
this.candleWs?.onHistoricalDataFetched(token.symbol, interval, candles);
|
|
135
|
-
return {
|
|
139
|
+
return {
|
|
140
|
+
symbol: token.symbol,
|
|
141
|
+
candles,
|
|
142
|
+
success: true
|
|
143
|
+
};
|
|
136
144
|
} catch (error) {
|
|
137
145
|
console.warn(`Failed to fetch historical data for ${token.symbol}:`, error);
|
|
138
|
-
return {
|
|
146
|
+
return {
|
|
147
|
+
symbol: token.symbol,
|
|
148
|
+
candles: [],
|
|
149
|
+
success: false
|
|
150
|
+
};
|
|
139
151
|
}
|
|
140
152
|
});
|
|
141
153
|
await Promise.all(fetchPromises);
|
|
@@ -158,7 +170,10 @@ class DataCollector {
|
|
|
158
170
|
this.cache.clear();
|
|
159
171
|
}
|
|
160
172
|
getAllTokens() {
|
|
161
|
-
return [
|
|
173
|
+
return [
|
|
174
|
+
...this.longTokens,
|
|
175
|
+
...this.shortTokens
|
|
176
|
+
];
|
|
162
177
|
}
|
|
163
178
|
syncTokenChanges() {
|
|
164
179
|
const currentSymbols = new Set(this.getAllTokens().map((t) => t.symbol));
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { getIntervalSeconds } from '../utils';
|
|
2
2
|
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
5
|
const BASE_URL = "https://mainnet.zklighter.elliot.ai";
|
|
4
6
|
const MAX_LIMIT = 500;
|
|
5
7
|
const RESOLUTION_MAP = {
|
|
@@ -10,8 +12,7 @@ const RESOLUTION_MAP = {
|
|
|
10
12
|
"1h": "1h",
|
|
11
13
|
"4h": "4h",
|
|
12
14
|
"12h": "12h",
|
|
13
|
-
"1d": "1d"
|
|
14
|
-
"1w": "1w"
|
|
15
|
+
"1d": "1d"
|
|
15
16
|
};
|
|
16
17
|
async function fetchHistoricalCandles(symbol, startTime, endTime, interval) {
|
|
17
18
|
const resolution = RESOLUTION_MAP[interval];
|
|
@@ -38,5 +39,6 @@ async function fetchHistoricalCandles(symbol, startTime, endTime, interval) {
|
|
|
38
39
|
c: candle.c ?? 0
|
|
39
40
|
}));
|
|
40
41
|
}
|
|
42
|
+
__name(fetchHistoricalCandles, "fetchHistoricalCandles");
|
|
41
43
|
|
|
42
44
|
export { fetchHistoricalCandles };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
1
3
|
const OKX_URL = "https://www.okx.com/api/v5/market/candles";
|
|
2
4
|
const MAX_LIMIT = 300;
|
|
3
5
|
const intervalMap = {
|
|
@@ -18,8 +20,16 @@ const intervalMap = {
|
|
|
18
20
|
};
|
|
19
21
|
function toCandleData(item) {
|
|
20
22
|
const startMs = Number(item[0]);
|
|
21
|
-
return {
|
|
23
|
+
return {
|
|
24
|
+
t: startMs,
|
|
25
|
+
T: startMs,
|
|
26
|
+
o: Number(item[1]),
|
|
27
|
+
h: Number(item[2]),
|
|
28
|
+
l: Number(item[3]),
|
|
29
|
+
c: Number(item[4])
|
|
30
|
+
};
|
|
22
31
|
}
|
|
32
|
+
__name(toCandleData, "toCandleData");
|
|
23
33
|
async function fetchHistoricalCandles(instId, startTime, endTime, interval) {
|
|
24
34
|
const params = new URLSearchParams({
|
|
25
35
|
instId,
|
|
@@ -34,5 +44,6 @@ async function fetchHistoricalCandles(instId, startTime, endTime, interval) {
|
|
|
34
44
|
if (data.code !== "0") throw new Error(`OKX API error: ${data.msg}`);
|
|
35
45
|
return data.data.reverse().map(toCandleData);
|
|
36
46
|
}
|
|
47
|
+
__name(fetchHistoricalCandles, "fetchHistoricalCandles");
|
|
37
48
|
|
|
38
49
|
export { fetchHistoricalCandles };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
1
3
|
function computeAssetBars(tokenCandles, symbol) {
|
|
2
4
|
const candles = tokenCandles[symbol];
|
|
3
5
|
if (!candles) return [];
|
|
@@ -9,6 +11,7 @@ function computeAssetBars(tokenCandles, symbol) {
|
|
|
9
11
|
close: c.c
|
|
10
12
|
}));
|
|
11
13
|
}
|
|
14
|
+
__name(computeAssetBars, "computeAssetBars");
|
|
12
15
|
function computeRealtimeAssetBar(snapshot, symbol) {
|
|
13
16
|
const candle = snapshot[symbol];
|
|
14
17
|
if (!candle) return null;
|
|
@@ -20,5 +23,6 @@ function computeRealtimeAssetBar(snapshot, symbol) {
|
|
|
20
23
|
close: candle.c
|
|
21
24
|
};
|
|
22
25
|
}
|
|
26
|
+
__name(computeRealtimeAssetBar, "computeRealtimeAssetBar");
|
|
23
27
|
|
|
24
28
|
export { computeAssetBars, computeRealtimeAssetBar };
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { createCandleLookups, getCompleteTimestamps } from '../utils';
|
|
2
2
|
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
5
|
function computePerformanceCandles(longTokens, shortTokens, tokenCandles) {
|
|
4
|
-
const empty = {
|
|
5
|
-
|
|
6
|
+
const empty = {
|
|
7
|
+
bars: [],
|
|
8
|
+
baselinePrices: {}
|
|
9
|
+
};
|
|
10
|
+
const allTokens = [
|
|
11
|
+
...longTokens,
|
|
12
|
+
...shortTokens
|
|
13
|
+
];
|
|
6
14
|
if (allTokens.length === 0) return empty;
|
|
7
15
|
const candleLookups = createCandleLookups(tokenCandles);
|
|
8
16
|
const allSymbols = allTokens.map((t) => t.symbol);
|
|
@@ -45,10 +53,17 @@ function computePerformanceCandles(longTokens, shortTokens, tokenCandles) {
|
|
|
45
53
|
close: portfolioValue
|
|
46
54
|
});
|
|
47
55
|
}
|
|
48
|
-
return {
|
|
56
|
+
return {
|
|
57
|
+
bars,
|
|
58
|
+
baselinePrices
|
|
59
|
+
};
|
|
49
60
|
}
|
|
61
|
+
__name(computePerformanceCandles, "computePerformanceCandles");
|
|
50
62
|
function computeRealtimePerformanceBar(longTokens, shortTokens, snapshot, baselinePrices) {
|
|
51
|
-
const allTokens = [
|
|
63
|
+
const allTokens = [
|
|
64
|
+
...longTokens,
|
|
65
|
+
...shortTokens
|
|
66
|
+
];
|
|
52
67
|
if (allTokens.length === 0) return null;
|
|
53
68
|
const initialPortfolioValue = 1e3;
|
|
54
69
|
const longSet = new Set(longTokens.map((t) => t.symbol));
|
|
@@ -77,5 +92,6 @@ function computeRealtimePerformanceBar(longTokens, shortTokens, snapshot, baseli
|
|
|
77
92
|
close: portfolioValue
|
|
78
93
|
};
|
|
79
94
|
}
|
|
95
|
+
__name(computeRealtimePerformanceBar, "computeRealtimePerformanceBar");
|
|
80
96
|
|
|
81
97
|
export { computePerformanceCandles, computeRealtimePerformanceBar };
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { createCandleLookups, getCompleteTimestamps } from '../utils';
|
|
2
2
|
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
5
|
function computePriceRatioCandles(longTokens, shortTokens, tokenCandles) {
|
|
4
6
|
if (longTokens.length === 0 && shortTokens.length === 0) return [];
|
|
5
7
|
const candleLookups = createCandleLookups(tokenCandles);
|
|
6
|
-
const allSymbols = [
|
|
8
|
+
const allSymbols = [
|
|
9
|
+
...longTokens,
|
|
10
|
+
...shortTokens
|
|
11
|
+
].map((t) => t.symbol);
|
|
7
12
|
const completeTimestamps = getCompleteTimestamps(candleLookups, allSymbols);
|
|
8
13
|
const bars = [];
|
|
9
14
|
for (const timestamp of completeTimestamps) {
|
|
@@ -61,6 +66,7 @@ function computePriceRatioCandles(longTokens, shortTokens, tokenCandles) {
|
|
|
61
66
|
}
|
|
62
67
|
return bars;
|
|
63
68
|
}
|
|
69
|
+
__name(computePriceRatioCandles, "computePriceRatioCandles");
|
|
64
70
|
function computeRealtimePriceRatioBar(longTokens, shortTokens, snapshot) {
|
|
65
71
|
let longSumO = 0;
|
|
66
72
|
let longSumH = 0;
|
|
@@ -103,5 +109,6 @@ function computeRealtimePriceRatioBar(longTokens, shortTokens, snapshot) {
|
|
|
103
109
|
close: longSumC / shortSumC
|
|
104
110
|
};
|
|
105
111
|
}
|
|
112
|
+
__name(computeRealtimePriceRatioBar, "computeRealtimePriceRatioBar");
|
|
106
113
|
|
|
107
114
|
export { computePriceRatioCandles, computeRealtimePriceRatioBar };
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { createCandleLookups, getCompleteTimestamps } from '../utils';
|
|
2
2
|
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
5
|
function pow(base, exponent) {
|
|
4
6
|
if (base <= 0) return 0;
|
|
5
7
|
return Math.exp(exponent * Math.log(base));
|
|
6
8
|
}
|
|
9
|
+
__name(pow, "pow");
|
|
7
10
|
function computeWeightedRatioCandles(longTokens, shortTokens, tokenCandles) {
|
|
8
11
|
if (longTokens.length === 0 && shortTokens.length === 0) return [];
|
|
9
12
|
const candleLookups = createCandleLookups(tokenCandles);
|
|
10
|
-
const allSymbols = [
|
|
13
|
+
const allSymbols = [
|
|
14
|
+
...longTokens,
|
|
15
|
+
...shortTokens
|
|
16
|
+
].map((t) => t.symbol);
|
|
11
17
|
const completeTimestamps = getCompleteTimestamps(candleLookups, allSymbols);
|
|
12
18
|
const bars = [];
|
|
13
19
|
for (const timestamp of completeTimestamps) {
|
|
@@ -64,6 +70,7 @@ function computeWeightedRatioCandles(longTokens, shortTokens, tokenCandles) {
|
|
|
64
70
|
}
|
|
65
71
|
return bars;
|
|
66
72
|
}
|
|
73
|
+
__name(computeWeightedRatioCandles, "computeWeightedRatioCandles");
|
|
67
74
|
function computeRealtimeWeightedRatioBar(longTokens, shortTokens, snapshot) {
|
|
68
75
|
let longOpen = 1;
|
|
69
76
|
let longHigh = 1;
|
|
@@ -105,5 +112,6 @@ function computeRealtimeWeightedRatioBar(longTokens, shortTokens, snapshot) {
|
|
|
105
112
|
close: longClose * shortClose
|
|
106
113
|
};
|
|
107
114
|
}
|
|
115
|
+
__name(computeRealtimeWeightedRatioBar, "computeRealtimeWeightedRatioBar");
|
|
108
116
|
|
|
109
117
|
export { computeRealtimeWeightedRatioBar, computeWeightedRatioCandles };
|
package/dist/chart/utils.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
const createKey = /* @__PURE__ */ __name((symbol, interval) => `${symbol}-${interval}`, "createKey");
|
|
4
|
+
const getIntervalSeconds = /* @__PURE__ */ __name((interval) => {
|
|
3
5
|
switch (interval) {
|
|
4
6
|
case "1m":
|
|
5
7
|
return 60;
|
|
@@ -30,21 +32,27 @@ const getIntervalSeconds = (interval) => {
|
|
|
30
32
|
case "1M":
|
|
31
33
|
return 30 * 24 * 60 * 60;
|
|
32
34
|
}
|
|
33
|
-
};
|
|
34
|
-
const mergeRanges = (ranges, newRange) => {
|
|
35
|
-
const all = [
|
|
35
|
+
}, "getIntervalSeconds");
|
|
36
|
+
const mergeRanges = /* @__PURE__ */ __name((ranges, newRange) => {
|
|
37
|
+
const all = [
|
|
38
|
+
...ranges,
|
|
39
|
+
newRange
|
|
40
|
+
].sort((a, b) => a.start - b.start);
|
|
36
41
|
const merged = [];
|
|
37
42
|
for (const r of all) {
|
|
38
43
|
const last = merged[merged.length - 1];
|
|
39
44
|
if (merged.length === 0 || !last || r.start > last.end) {
|
|
40
|
-
merged.push({
|
|
45
|
+
merged.push({
|
|
46
|
+
start: r.start,
|
|
47
|
+
end: r.end
|
|
48
|
+
});
|
|
41
49
|
} else {
|
|
42
50
|
last.end = Math.max(last.end, r.end);
|
|
43
51
|
}
|
|
44
52
|
}
|
|
45
53
|
return merged;
|
|
46
|
-
};
|
|
47
|
-
const createCandleLookups = (tokenCandles) => {
|
|
54
|
+
}, "mergeRanges");
|
|
55
|
+
const createCandleLookups = /* @__PURE__ */ __name((tokenCandles) => {
|
|
48
56
|
const lookups = {};
|
|
49
57
|
for (const [symbol, candles] of Object.entries(tokenCandles)) {
|
|
50
58
|
const lookup = /* @__PURE__ */ new Map();
|
|
@@ -54,8 +62,8 @@ const createCandleLookups = (tokenCandles) => {
|
|
|
54
62
|
lookups[symbol] = lookup;
|
|
55
63
|
}
|
|
56
64
|
return lookups;
|
|
57
|
-
};
|
|
58
|
-
const getCompleteTimestamps = (candleLookups, requiredSymbols) => {
|
|
65
|
+
}, "createCandleLookups");
|
|
66
|
+
const getCompleteTimestamps = /* @__PURE__ */ __name((candleLookups, requiredSymbols) => {
|
|
59
67
|
if (requiredSymbols.length === 0) return [];
|
|
60
68
|
let baseSymbol;
|
|
61
69
|
let baseLookup;
|
|
@@ -86,6 +94,6 @@ const getCompleteTimestamps = (candleLookups, requiredSymbols) => {
|
|
|
86
94
|
}
|
|
87
95
|
result.sort((a, b) => a - b);
|
|
88
96
|
return result;
|
|
89
|
-
};
|
|
97
|
+
}, "getCompleteTimestamps");
|
|
90
98
|
|
|
91
99
|
export { createCandleLookups, createKey, getCompleteTimestamps, getIntervalSeconds, mergeRanges };
|
|
@@ -6,6 +6,10 @@ import 'partysocket';
|
|
|
6
6
|
import '../../transport/index.js';
|
|
7
7
|
|
|
8
8
|
type CandleHandler = (symbol: string, candle: CandleData) => void;
|
|
9
|
+
type ParsedCandle = {
|
|
10
|
+
symbol: string;
|
|
11
|
+
candle: CandleData;
|
|
12
|
+
};
|
|
9
13
|
declare abstract class BaseCandleWs {
|
|
10
14
|
protected transport: BaseTransport;
|
|
11
15
|
protected onCandle: CandleHandler;
|
|
@@ -14,10 +18,12 @@ declare abstract class BaseCandleWs {
|
|
|
14
18
|
private subscribedKeys;
|
|
15
19
|
protected abstract buildSubscribeMessage(symbol: string, interval: CandleInterval): WsMessage;
|
|
16
20
|
protected abstract buildUnsubscribeMessage(symbol: string, interval: CandleInterval): WsMessage;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
/**
|
|
22
|
+
* One venue message can carry several candles: on rollover Lighter sends the just-closed period
|
|
23
|
+
* alongside the freshly opened one, and dropping the closed one would leave that bar missing its
|
|
24
|
+
* final trades. Venues that only ever send one candle return a single-element array.
|
|
25
|
+
*/
|
|
26
|
+
protected abstract parseMessages(data: string): ParsedCandle[];
|
|
21
27
|
constructor(transport: BaseTransport, onCandle: CandleHandler);
|
|
22
28
|
start(): void;
|
|
23
29
|
stop(): void;
|
|
@@ -27,4 +33,4 @@ declare abstract class BaseCandleWs {
|
|
|
27
33
|
unsubscribe(symbol: string, interval: CandleInterval): void;
|
|
28
34
|
}
|
|
29
35
|
|
|
30
|
-
export { BaseCandleWs, type CandleHandler };
|
|
36
|
+
export { BaseCandleWs, type CandleHandler, type ParsedCandle };
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
1
3
|
class BaseCandleWs {
|
|
4
|
+
static {
|
|
5
|
+
__name(this, "BaseCandleWs");
|
|
6
|
+
}
|
|
2
7
|
transport;
|
|
3
8
|
onCandle;
|
|
4
9
|
messageListenerId = null;
|
|
@@ -11,8 +16,7 @@ class BaseCandleWs {
|
|
|
11
16
|
start() {
|
|
12
17
|
if (this.messageListenerId) return;
|
|
13
18
|
this.messageListenerId = this.transport.addMessageListener((data) => {
|
|
14
|
-
const result
|
|
15
|
-
if (result) {
|
|
19
|
+
for (const result of this.parseMessages(data)) {
|
|
16
20
|
this.onCandle(result.symbol, result.candle);
|
|
17
21
|
}
|
|
18
22
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { WsMessage } from '../../shared/types.js';
|
|
2
|
-
import { CandleInterval
|
|
3
|
-
import { BaseCandleWs } from './base-candle.js';
|
|
2
|
+
import { CandleInterval } from '../types.js';
|
|
3
|
+
import { BaseCandleWs, ParsedCandle } from './base-candle.js';
|
|
4
4
|
import '../../transport/index.js';
|
|
5
5
|
import '@pear-protocol/types';
|
|
6
6
|
import '../../transport/base-transport.js';
|
|
@@ -10,10 +10,8 @@ declare class BinanceCandleWs extends BaseCandleWs {
|
|
|
10
10
|
private idCounter;
|
|
11
11
|
protected buildSubscribeMessage(symbol: string, interval: CandleInterval): WsMessage;
|
|
12
12
|
protected buildUnsubscribeMessage(symbol: string, interval: CandleInterval): WsMessage;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
candle: CandleData;
|
|
16
|
-
} | null;
|
|
13
|
+
/** Translates one Binance kline frame into a single-candle batch. */
|
|
14
|
+
protected parseMessages(data: string): ParsedCandle[];
|
|
17
15
|
}
|
|
18
16
|
|
|
19
17
|
export { BinanceCandleWs };
|