bandkit 1.0.4 → 1.0.6
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/README.md +17 -14
- package/dist/AnimatedNumber.d.ts +10 -0
- package/dist/AnimatedNumber.d.ts.map +1 -0
- package/dist/AnimatedNumber.js +35 -0
- package/dist/AnimatedNumber.js.map +1 -0
- package/dist/BotDecisionPanel.d.ts.map +1 -1
- package/dist/BotDecisionPanel.js +15 -3
- package/dist/BotDecisionPanel.js.map +1 -1
- package/dist/ContractEventFeed.d.ts.map +1 -1
- package/dist/ContractEventFeed.js +14 -1
- package/dist/ContractEventFeed.js.map +1 -1
- package/dist/GasBadge.d.ts.map +1 -1
- package/dist/GasBadge.js +10 -2
- package/dist/GasBadge.js.map +1 -1
- package/dist/OrderBookWidget.d.ts.map +1 -1
- package/dist/OrderBookWidget.js +27 -3
- package/dist/OrderBookWidget.js.map +1 -1
- package/dist/RegimeBadge.d.ts.map +1 -1
- package/dist/RegimeBadge.js +3 -1
- package/dist/RegimeBadge.js.map +1 -1
- package/dist/Skeleton.d.ts +15 -0
- package/dist/Skeleton.d.ts.map +1 -0
- package/dist/Skeleton.js +26 -0
- package/dist/Skeleton.js.map +1 -0
- package/dist/StrategyValueSparkline.d.ts +9 -0
- package/dist/StrategyValueSparkline.d.ts.map +1 -0
- package/dist/StrategyValueSparkline.js +99 -0
- package/dist/StrategyValueSparkline.js.map +1 -0
- package/dist/TradeTape.d.ts.map +1 -1
- package/dist/TradeTape.js +20 -7
- package/dist/TradeTape.js.map +1 -1
- package/dist/decisionEngine.d.ts.map +1 -1
- package/dist/decisionEngine.js +51 -25
- package/dist/decisionEngine.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/useStrategyValueHistory.d.ts +24 -0
- package/dist/useStrategyValueHistory.d.ts.map +1 -0
- package/dist/useStrategyValueHistory.js +112 -0
- package/dist/useStrategyValueHistory.js.map +1 -0
- package/package.json +1 -1
- package/scripts/test-decision-stream.cjs +38 -18
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bandkit",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "Open-source scaffolding for Ethereum range-bound trading strategies: strategy contract deployment, restricted executor, and React hooks. Strategy logic is not included.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -97,6 +97,11 @@ function classifyRegime(prices) {
|
|
|
97
97
|
return { regime, stddevPct, driftPct };
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
function softCap(raw, ceiling = 88, scale = 55) {
|
|
101
|
+
const bounded = Math.max(0, raw);
|
|
102
|
+
return Math.round(ceiling * (1 - Math.exp(-bounded / scale)));
|
|
103
|
+
}
|
|
104
|
+
|
|
100
105
|
function computeDecision(inputs) {
|
|
101
106
|
const reasons = [];
|
|
102
107
|
if (inputs.regime === "UNKNOWN") {
|
|
@@ -105,72 +110,87 @@ function computeDecision(inputs) {
|
|
|
105
110
|
if (inputs.regime === "TRENDING") {
|
|
106
111
|
return {
|
|
107
112
|
decision: "STAND DOWN",
|
|
108
|
-
confidence:
|
|
113
|
+
confidence: 72,
|
|
109
114
|
reasons: ["TRENDING regime — bot sits out"]
|
|
110
115
|
};
|
|
111
116
|
}
|
|
112
117
|
|
|
113
118
|
let scoreBuy = 0;
|
|
114
119
|
let scoreSell = 0;
|
|
115
|
-
let
|
|
120
|
+
let baseScore = inputs.regime === "RANGING" ? 25 : 12;
|
|
116
121
|
reasons.push(`Regime: ${inputs.regime}`);
|
|
117
122
|
|
|
123
|
+
const absBook = Math.abs(inputs.bookImbalance);
|
|
118
124
|
if (inputs.bookImbalance >= 0.15) {
|
|
119
|
-
scoreBuy +=
|
|
125
|
+
scoreBuy += 8 + Math.min(10, (absBook - 0.15) * 18);
|
|
120
126
|
reasons.push(`Book +${(inputs.bookImbalance * 100).toFixed(0)}% bid`);
|
|
121
127
|
} else if (inputs.bookImbalance <= -0.15) {
|
|
122
|
-
scoreSell +=
|
|
128
|
+
scoreSell += 8 + Math.min(10, (absBook - 0.15) * 18);
|
|
123
129
|
reasons.push(`Book ${(inputs.bookImbalance * 100).toFixed(0)}% ask`);
|
|
124
130
|
} else {
|
|
125
131
|
reasons.push(`Book ${(inputs.bookImbalance * 100).toFixed(0)}%`);
|
|
126
132
|
}
|
|
127
133
|
|
|
134
|
+
const absFlow = Math.abs(inputs.tradeImbalance);
|
|
128
135
|
if (inputs.tradeImbalance >= 0.10) {
|
|
129
|
-
scoreBuy += 20;
|
|
136
|
+
scoreBuy += 6 + Math.min(8, (absFlow - 0.10) * 20);
|
|
130
137
|
reasons.push(`Flow ${((0.5 + inputs.tradeImbalance / 2) * 100).toFixed(0)}% buys`);
|
|
131
138
|
} else if (inputs.tradeImbalance <= -0.10) {
|
|
132
|
-
scoreSell += 20;
|
|
139
|
+
scoreSell += 6 + Math.min(8, (absFlow - 0.10) * 20);
|
|
133
140
|
reasons.push(`Flow ${((0.5 - inputs.tradeImbalance / 2) * 100).toFixed(0)}% sells`);
|
|
134
141
|
} else {
|
|
135
142
|
reasons.push("Flow balanced");
|
|
136
143
|
}
|
|
137
144
|
|
|
138
145
|
if (inputs.spreadPct > 0.05) {
|
|
139
|
-
|
|
146
|
+
baseScore -= 8;
|
|
140
147
|
reasons.push(`Spread wide ${inputs.spreadPct.toFixed(3)}%`);
|
|
141
148
|
} else {
|
|
142
|
-
|
|
149
|
+
baseScore += 3;
|
|
143
150
|
}
|
|
144
151
|
|
|
145
152
|
if (inputs.venueDivergenceBps !== null && Number.isFinite(inputs.venueDivergenceBps)) {
|
|
153
|
+
const absDiv = Math.abs(inputs.venueDivergenceBps);
|
|
146
154
|
if (inputs.venueDivergenceBps > 5) {
|
|
147
|
-
scoreBuy +=
|
|
155
|
+
scoreBuy += 4 + Math.min(6, (absDiv - 5) * 0.6);
|
|
148
156
|
reasons.push(`BIN +${inputs.venueDivergenceBps.toFixed(1)}bps`);
|
|
149
157
|
} else if (inputs.venueDivergenceBps < -5) {
|
|
150
|
-
scoreSell +=
|
|
158
|
+
scoreSell += 4 + Math.min(6, (absDiv - 5) * 0.6);
|
|
151
159
|
reasons.push(`BIN ${inputs.venueDivergenceBps.toFixed(1)}bps`);
|
|
152
160
|
}
|
|
153
161
|
}
|
|
154
162
|
|
|
155
163
|
if (inputs.bookDepth < 50) {
|
|
156
|
-
|
|
164
|
+
baseScore -= 10;
|
|
157
165
|
reasons.push(`Thin book (${inputs.bookDepth.toFixed(0)} ETH)`);
|
|
158
166
|
} else {
|
|
159
|
-
|
|
167
|
+
baseScore += 3;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Conflicting-signal penalty
|
|
171
|
+
if (scoreBuy > 0 && scoreSell > 0) {
|
|
172
|
+
if (scoreBuy >= scoreSell) {
|
|
173
|
+
scoreBuy -= scoreSell * 0.7;
|
|
174
|
+
scoreSell = 0;
|
|
175
|
+
} else {
|
|
176
|
+
scoreSell -= scoreBuy * 0.7;
|
|
177
|
+
scoreBuy = 0;
|
|
178
|
+
}
|
|
160
179
|
}
|
|
161
180
|
|
|
162
181
|
let decision = "WAIT";
|
|
163
|
-
|
|
182
|
+
let confidence;
|
|
183
|
+
if (scoreBuy > scoreSell + 6) {
|
|
164
184
|
decision = "BUY";
|
|
165
|
-
confidence =
|
|
166
|
-
} else if (scoreSell > scoreBuy +
|
|
185
|
+
confidence = softCap(baseScore + scoreBuy);
|
|
186
|
+
} else if (scoreSell > scoreBuy + 6) {
|
|
167
187
|
decision = "SELL";
|
|
168
|
-
confidence =
|
|
188
|
+
confidence = softCap(baseScore + scoreSell);
|
|
169
189
|
} else {
|
|
170
|
-
confidence =
|
|
190
|
+
confidence = softCap(Math.max(baseScore / 2, 5), 55, 35);
|
|
171
191
|
}
|
|
172
192
|
|
|
173
|
-
return { decision, confidence
|
|
193
|
+
return { decision, confidence, reasons };
|
|
174
194
|
}
|
|
175
195
|
|
|
176
196
|
// ---- WebSocket setup -----------------------------------------------------
|