The autonomous trading runtime behind onaeterna.com.
One structured workflow for any frontier model. The market environment, execution rules, tools, and risk framework stay constant. The intelligence layer is interchangeable.
Every agent runs the same eight-phase cycle:
| Phase | Name | What happens |
|---|---|---|
| I | Research | Price action, news, sentiment, macro |
| II | Reason | A structured market view |
| III | Signal | Direction, confidence, thesis, horizon |
| IV | Risk | Policy and portfolio constraints |
| V | Execute | Trades on tokenized stocks |
| VI | Observe | Fills, PnL, thesis validity |
| VII | Remember | Structured memory of outcomes |
| VIII | Adapt | Better context, next cycle |
The open, model-agnostic runtime core:
Harness— the eight-phase loop orchestrator (src/loop.ts)RiskEngine— confidence, sizing, exposure, and drawdown policy (src/risk.ts)OpenAICompatibleClient— works with any/chat/completionsgateway (src/inference.ts)PaperBroker— instant-fill paper execution for end-to-end runs (src/paper.ts)InMemoryStore— cycle memory for paper runs and tests (src/memory.ts)- Provider interfaces — plug in your own market data, broker, memory, and
inference implementations (
src/providers.ts)
Production adapters (live market data feeds, execution venues, persistent memory) and deployment configuration are not part of this repository.
npm install
INFERENCE_API_URL=https://api.example.com/v1 \
INFERENCE_API_KEY=sk-... \
INFERENCE_MODEL=your-model-id \
npm run exampleThis runs five cycles of the full loop against a toy random-walk market with a paper broker. Any OpenAI-compatible chat-completions endpoint works.
import {
Harness,
InMemoryStore,
OpenAICompatibleClient,
PaperBroker,
RiskEngine,
} from "aeterna-harness";
const harness = new Harness({
universe: ["AAPLx", "NVDAx", "SPYx"],
inference: new OpenAICompatibleClient(),
marketData: myMarketDataProvider, // implement MarketDataProvider
broker: new PaperBroker(100_000), // or implement Broker
memory: new InMemoryStore(),
risk: new RiskEngine({
maxPositionPct: 0.15,
maxOpenPositions: 5,
minConfidence: 0.55,
maxDrawdownPct: 20,
baseSizePct: 0.05,
}),
});
const record = await harness.runCycle();Swap the model by changing INFERENCE_MODEL — nothing else in the harness
changes. That is the point.
MIT