@senpi/trading-recipe 1.0.57 → 1.0.58
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.
|
@@ -20,6 +20,7 @@ import { tmpdir } from "node:os";
|
|
|
20
20
|
import { join } from "node:path";
|
|
21
21
|
import {
|
|
22
22
|
createScannerRuntimeModule,
|
|
23
|
+
buildCompositionFromScanners,
|
|
23
24
|
emergingMoversScanner,
|
|
24
25
|
} from "../dist/scanners/index.js";
|
|
25
26
|
|
|
@@ -187,7 +188,7 @@ async function main() {
|
|
|
187
188
|
|
|
188
189
|
const module = createScannerRuntimeModule({
|
|
189
190
|
stateDir,
|
|
190
|
-
|
|
191
|
+
...buildCompositionFromScanners([emergingMoversScanner]),
|
|
191
192
|
strategies: [
|
|
192
193
|
{
|
|
193
194
|
id: "wolf",
|
|
@@ -218,6 +219,7 @@ async function main() {
|
|
|
218
219
|
},
|
|
219
220
|
],
|
|
220
221
|
providers: {
|
|
222
|
+
getInstruments: async () => [],
|
|
221
223
|
getSmData: async () => {
|
|
222
224
|
const data = SCAN_DATA[scanIndex]();
|
|
223
225
|
scanIndex++;
|
|
@@ -13,6 +13,7 @@ import { tmpdir } from "node:os";
|
|
|
13
13
|
import { join } from "node:path";
|
|
14
14
|
import {
|
|
15
15
|
createScannerRuntimeModule,
|
|
16
|
+
buildCompositionFromScanners,
|
|
16
17
|
liquidationWatchdogScanner,
|
|
17
18
|
} from "../dist/scanners/index.js";
|
|
18
19
|
import { StateManager } from "../dist/state/index.js";
|
|
@@ -21,31 +22,41 @@ import { StateManager } from "../dist/state/index.js";
|
|
|
21
22
|
|
|
22
23
|
function makeClearingHouseState({ bufferPct, positions }) {
|
|
23
24
|
// bufferPct controls how much margin room is left:
|
|
24
|
-
// buffer = (
|
|
25
|
-
// →
|
|
25
|
+
// buffer = (withdrawable / accountValue) * 100
|
|
26
|
+
// → withdrawable = accountValue * (bufferPct / 100)
|
|
26
27
|
const accountValue = 10_000;
|
|
27
|
-
const
|
|
28
|
+
const withdrawable = accountValue * (bufferPct / 100);
|
|
29
|
+
const totalMarginUsed = accountValue - withdrawable;
|
|
28
30
|
return {
|
|
29
31
|
accountValue,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
withdrawable,
|
|
33
|
+
totalMarginUsed,
|
|
34
|
+
totalUnrealizedPnl: 0,
|
|
35
|
+
totalNtlPos: 0,
|
|
33
36
|
positions: positions ?? [],
|
|
34
37
|
};
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
function makePosition({ asset, direction, markPrice, liqPrice, roe, marginType }) {
|
|
41
|
+
// Scanner expects StrategyOpenPosition from types/strategy.ts:
|
|
42
|
+
// coin, dex, szi, entryPx, leverage, leverageType, unrealizedPnl, marginUsed, liquidationPx, returnOnEquity
|
|
43
|
+
// szi sign encodes direction: positive = LONG, negative = SHORT
|
|
44
|
+
// returnOnEquity is a ratio (e.g. 0.05 for 5%), scanner multiplies by 100
|
|
45
|
+
const dir = direction ?? "LONG";
|
|
46
|
+
const szi = dir === "SHORT" ? -1 : 1;
|
|
47
|
+
const entryPx = markPrice * 0.95;
|
|
48
|
+
const unrealizedPnl = (markPrice - entryPx) * szi;
|
|
38
49
|
return {
|
|
39
|
-
asset,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
markPrice,
|
|
44
|
-
liquidationPrice: liqPrice ?? null,
|
|
45
|
-
unrealizedPnl: markPrice * 0.05,
|
|
46
|
-
roe: roe ?? 5,
|
|
50
|
+
coin: asset,
|
|
51
|
+
dex: "",
|
|
52
|
+
szi,
|
|
53
|
+
entryPx,
|
|
47
54
|
leverage: 5,
|
|
48
|
-
|
|
55
|
+
leverageType: marginType ?? "cross",
|
|
56
|
+
unrealizedPnl,
|
|
57
|
+
marginUsed: entryPx / 5,
|
|
58
|
+
liquidationPx: liqPrice ?? null,
|
|
59
|
+
returnOnEquity: (roe ?? 5) / 100,
|
|
49
60
|
};
|
|
50
61
|
}
|
|
51
62
|
|
|
@@ -79,7 +90,7 @@ async function scenarioWithoutDslStates() {
|
|
|
79
90
|
|
|
80
91
|
const module = createScannerRuntimeModule({
|
|
81
92
|
stateDir,
|
|
82
|
-
|
|
93
|
+
...buildCompositionFromScanners([liquidationWatchdogScanner]),
|
|
83
94
|
strategies: [
|
|
84
95
|
{
|
|
85
96
|
id: "wallet-001",
|
|
@@ -227,7 +238,7 @@ async function scenarioWithDslStates() {
|
|
|
227
238
|
});
|
|
228
239
|
|
|
229
240
|
// Verify StateManager has the states
|
|
230
|
-
const loaded = stateManager.listDslStates("wallet-002");
|
|
241
|
+
const loaded = await stateManager.listDslStates("wallet-002");
|
|
231
242
|
console.log(" StateManager DSL states loaded:", loaded.length);
|
|
232
243
|
console.assert(loaded.length === 2, "Expected 2 DSL states in StateManager");
|
|
233
244
|
|
|
@@ -243,7 +254,7 @@ async function scenarioWithDslStates() {
|
|
|
243
254
|
// Wire getDslStatesForStrategy to read from the StateManager — same as Runtime does
|
|
244
255
|
const module = createScannerRuntimeModule({
|
|
245
256
|
stateDir,
|
|
246
|
-
|
|
257
|
+
...buildCompositionFromScanners([liquidationWatchdogScanner]),
|
|
247
258
|
strategies: [
|
|
248
259
|
{
|
|
249
260
|
id: "wallet-002",
|
|
@@ -3,6 +3,7 @@ import { tmpdir } from "node:os";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import {
|
|
5
5
|
createScannerRuntimeModule,
|
|
6
|
+
buildCompositionFromScanners,
|
|
6
7
|
oiTrackerScanner,
|
|
7
8
|
} from "../dist/scanners/index.js";
|
|
8
9
|
|
|
@@ -39,7 +40,7 @@ async function main() {
|
|
|
39
40
|
|
|
40
41
|
const module = createScannerRuntimeModule({
|
|
41
42
|
stateDir,
|
|
42
|
-
|
|
43
|
+
...buildCompositionFromScanners([oiTrackerScanner]),
|
|
43
44
|
strategies: [
|
|
44
45
|
{
|
|
45
46
|
id: "alpha",
|
package/openclaw.plugin.json
CHANGED