feat: strategy what-if simulation endpoint (#344) - #415
Merged
Abidoyesimze merged 1 commit intoSep 2, 2026
Merged
Conversation
Add POST /api/v1/strategies/simulate — a dry-run what-if preview that resolves the caller's effective strategy config (follow -> inline -> own, risk ceiling tighten-only), then returns an immediate engine-parity decision plus a non-compounding historical replay against retained ProtocolRate history, side-by-side with a counterfactual hold leg. All accrual math uses Prisma.Decimal. The module is a pure read with zero side effects: it never writes an OutboxOp, AgentLog, Transaction, RebalanceDecision, User, PublishedStrategy or Position row. Enforced structurally (no stellar/db/event imports in the core) and by test. Includes a 120s result cache keyed by a config+window simulation token, a 6 req/min simulate rate limiter, validators, unit + integration tests, and docs (openapi, STRATEGY_MARKETPLACE, ASSUMPTIONS).
|
@BernardOnuh Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #344
Summary
Adds
POST /api/v1/strategies/simulate(#344) — a dry-run what-if preview for a hypothetical strategy change before the user commits to it.The endpoint resolves the caller's effective strategy config (follow → inline → own, risk ceiling tighten-only), then returns:
immediate— what the agent would do right now on the caller's live positions (rebalance/hold/blocked) plus atracethat is shape-parity with the persistedDecisionTrace.historical— a non-compounding daily replay over retainedProtocolRatehistory, side-by-side with a counterfactual "held in the starting protocol" leg. Each rebalance subtracts the sameestimateRebalanceCostthe live agent uses.All accrual math uses
Prisma.Decimal(never a plain float).Zero side effects
The endpoint is a pure read — it never writes an
OutboxOp,AgentLog,Transaction,RebalanceDecision,User,PublishedStrategy, orPositionrow. Enforced structurally in the core (src/agent/simulate.tshas nostellar/db/event imports — verified by a source-reading test) and by acceptance tests at the DB-glue layer.Deliberate decisions (callouts)
value × 10^18(thesrc/agent/backtest.tsconvention) so the sharedestimateRebalanceCostdivides back to human units and yields realistic fees. We deliberately do not mirror the latent plain-integer encoding insrc/agent/tools/actionTools.ts:265, which would drive network-fee percent toward ~1e15 and block every move. Documented inASSUMPTIONS.md/STRATEGY_MARKETPLACE.md.confirmSimulationToken/PUT /api/v1/strategyapply step — that endpoint does not exist yet; strategy changes go throughadjustStrategyTool).Files
New
src/agent/simulate.ts— pure simulation coresrc/strategy/simulation-service.ts— owner-scoped DB glue (reads only caller positions + public rates/risk scores)tests/unit/agent/simulate.test.ts(12 tests)tests/integration/strategies-simulate.integration.test.ts(7 tests)Changed
src/routes/strategies.ts,src/controllers/strategy-controller.ts— the routesrc/validators/strategy-validators.ts—strategySimulateSchema(180-day cap, follow/inline mutual exclusion)src/config/env.ts,src/middleware/rateLimiter.ts—simulateRateLimit(6 req/min)tests/integration/rateLimiter.integration.test.ts— mock block for the new limiterdocs/openapi.yaml,docs/STRATEGY_MARKETPLACE.md,ASSUMPTIONS.mdVerification
npm run typecheck✅npm run lint✅npm test✅ (123 suites / 1665 tests pass)Note:
package-lock.jsonwas left out of this PR — it only picked up adev: truemetadata tweak from a localnpm installand is unrelated to the feature.