Version update — 6 October 2026. The current stable release is v0.1.1, released on 4 October 2026. Real broker order submission remains disabled. The architecture discussion, demo commands, output and capability table below document the v0.1.0-rc.1 snapshot checked on 1 October; they have not been rerun against v0.1.1. See the project page for current status.
In the previous note, I wrote about how KabuForge grew from a collection of Colab notebooks. This article is about what the system has become.
KabuForge is an open-source, local-first research framework for systematic Japanese equity investing. I use it to connect data, factors, strategies, portfolio construction, risk controls, order planning, historical backtesting, local paper simulation and agent interfaces through explicit contracts.
It is not a proprietary stock-picking model, a particular investment strategy or an AI stock recommender. It is also not a J-Quants GUI or a live trading bot. The historical release documented here, v0.1.0-rc.1, does not enable real broker order submission.
What it provides is the research and decision infrastructure in which strategies can be defined, tested, compared and inspected. The same decisions can then be evaluated in different execution environments. That is a larger problem than writing a collection of backtest functions, even though backtesting remains an essential part of it.
A backtest is only one part of the problem
Calculating a historical return series in Python is usually the easy part. Once I have several experiments, the less visible questions start to matter: which data did this run use? Did that financial statement exist at the decision time? Does this strategy return weights or orders? If I run it in a paper account, will its stock selection change because a different price happens to be available?
I also need to understand an old experiment without reconstructing the notebook session that produced it. An agent needs the same ability, with fewer opportunities to take shortcuts.
A research system should define not only calculations, but the boundaries between calculations. Those boundaries tell me what a component may consume, what its result means and which part of the system is responsible for the next decision. I arrived at these separations while trying to make the project easier to reason about; they were not all present at the beginning.
The decision pipeline
PIT Data Snapshot
↓
Factor
↓
Strategy
↓
TargetPortfolio
↓
Risk
↓
Planner
↓
OrderIntentThe pipeline begins with a point-in-time data snapshot: the information visible at a particular decision time. A factor measures something in that snapshot. A strategy uses those observations to express a desired portfolio. Risk checks whether that proposed state is permitted. The planner compares the permitted target with the account's current state and produces broker-neutral order intentions.
Each stage answers a different question. Data determines what I could know. A factor determines what I observe. A strategy determines what portfolio I want. A target records that desired state. Risk constrains it. Planning determines how to move toward it. An order intention describes an action that an execution environment can interpret.
The diagram is a conceptual flow, not a requirement to rebalance at every decision. A strategy can return no new target when no adjustment is needed.
Strategy, portfolio and order are different objects. Treating them as interchangeable makes a small backtest convenient, but makes later comparison difficult. I want to be able to change the execution environment without quietly changing the research question.
A factor is a research unit
The factor contract can be read as:
FactorSpec + FactorContext → FactorResultA Python function such as my_factor(df) can calculate a useful number. Its signature does not necessarily tell me which universe it represents, the decision date, the parameter set or the data snapshot. It may also leave the meaning of the output implicit: a raw observation, a cross-sectional rank and a desired portfolio weight are not interchangeable.
KabuForge gives a factor an explicit specification and context, then records an identifiable result. Registered factor implementations give a research unit a name and version that can be referred to by later runs. The context supplies the conditions under which the calculation occurs.
For example, a momentum calculation for a broad universe and the same calculation for a filtered universe may share code while answering different research questions. A changed lookback window is another experiment. I need those differences to be visible in the run's identity rather than buried in a mutable notebook variable.
This does not determine which factor I should study. Research freedom remains in the implementation and specification. The contract makes that freedom inspectable. Configuration selects approved registered implementations; it is not a request to import arbitrary Python code or evaluate an expression.
Existing now does not mean knowable then
A reporting period and an information availability time describe different things. A financial statement for a quarter ending in March might be published in May. A March decision cannot use it merely because its period label says March.
KabuForge uses available_at to express when information becomes visible. Strict inputs use timezone-aware timestamps, and future-visible rows are excluded from earlier decisions. The principle is simple: a research decision should consume only information visible at its decision time.
Look-ahead does not require an obvious indexing bug. A current download can contain revised values, a corrected announcement timestamp or a universe assembled with today's knowledge. Joining these into a historical panel can produce a plausible calculation with an impossible information set.
A PIT-aware framework cannot make an external dataset historically PIT-complete. Visibility checks enforce the supplied availability metadata. They cannot establish that an upstream vendor retained every original vintage or correctly recorded every historical publication. Dataset provenance and revision policy still need examination. I do not treat the framework's checks as certification of all J-Quants or other external data.
A strategy produces a target, not a trade
Consider an illustrative target with Toyota at 5% and Sony at 5%. These weights are a synthetic example, not recommendations. The strategy has expressed a desired exposure. It has not yet decided to buy Toyota 300 shares or sell Sony 100 shares.
FactorResult(s) → Strategy → StrategyDecision → TargetPortfolioThe share counts depend on portfolio value, cash, prices and lot sizes. They also depend on what I already own. An account already at the target may require no order; an empty account and an account with an oversized position require different actions for the same target.
For a small account, a nominal 5% allocation may be below the minimum tradable lot. A planner needs to handle that constraint explicitly. It should not force the strategy to redefine its stock-selection rule just to manufacture a share count.
The target therefore carries the portfolio decision into a separate process:
TargetPortfolio → Risk → Planner → OrderIntentAn order intention is still not a confirmed fill. It describes a broker-neutral action derived from the decision and account state. A simulator or adapter must determine what happens to that intention under its own execution rules.
Risk belongs in the decision process
Volatility, Sharpe ratio and drawdown are useful diagnostics. Reporting them after a run does not constrain the portfolio that a strategy proposes.
A risk policy operates between the target and planning. It can approve, adjust or reject the proposed target according to the configured policy. A concentration limit, for example, can prevent a large proposed allocation from proceeding unchanged. The resulting permitted target is what the planner works with.
That location matters. If a backtest applies a restriction only in its reporting code while paper operation applies it before orders, the two workflows are studying different decisions. Recording the proposed target and risk outcome also makes the difference between strategy intent and permitted exposure easier to inspect.
The existence of this layer does not establish that a particular policy is adequate for production trading. Its rules and assumptions still need to be tested.
Same decisions, different execution environments
→ Historical Backtest
OrderIntent → Paper Simulation
⇢ Broker Adapter
Validation only; real submission disabledA historical simulator and a paper environment have different clocks and state. Historical fills may use a defined price model and cost assumptions. Paper simulation must deal with the current account state, cash and the timing of local operation. Neither should be presented as a measurement of live fills.
The design goal is not identical fills everywhere. It is the same research and decision semantics across different operating environments: the same factor meaning, strategy target, risk boundary and planning responsibility.
Execution differences remain explicit. A later execution price must not reach backward and reselect an earlier strategy target. If a comparison produces different outcomes, I want to locate the difference in information, configuration or execution assumptions rather than guess which layer silently changed.
The broker-adapter branch is shown separately because protocol mappings and mocks are a validation layer in this RC. A tested mapping is not an enabled live broker connection.
Real execution is not Boolean
Suppose an external order request is sent and the connection fails before the response arrives. The client does not know whether the remote system accepted it. Calling that a failure and submitting again could duplicate the action. Calling it a success would invent evidence.
UNKNOWN is an explicit execution state for that ambiguity. It preserves the fact that an outcome needs reconciliation rather than turning missing information into a confident answer.
Idempotency gives a repeated operation a stable identity. Receipts preserve what was attempted and what was observed. Reconciliation checks authoritative state before deciding whether another action is appropriate. Together, these mechanisms make a retry a domain decision instead of a casual second network request. They do not guarantee exactly-once behavior from every remote system.
This describes the execution model and its validation paths. Real broker order submission remains disabled in v0.1.0-rc.1. The architecture can account for uncertainty without claiming that the current release is ready to place live orders.
The current implementation blocks new submission while an operation is submitting or unknown and requires reconciliation evidence to leave an ambiguous state. This is not a claim that automatic reconciliation or resubmission against a real broker is implemented.
Agent-operable does not mean agent-controlled
GUI ─┐
CLI ─┼→ Application Services → Research / Risk / Planning
MCP ─┘I wanted the research environment itself to be operable by agents. A chatbot attached to a backtester would not solve the question of which operations it may perform or which rules those operations must obey.
GUI, CLI and MCP are clients of the application boundary. An agent can inspect factors and strategies, validate a specification, run local research, compare backtests and read the resulting evidence. It does not receive a privileged route around the domain model. The interface changes; the domain contracts do not.
The current MCP access levels distinguish consequences:
| Level | Boundary in this RC |
|---|---|
| R0 — Read | Inspection is enabled by default |
| R1 — Local compute | Local research is enabled by default |
| R2 — Local mutation | Explicit opt-in; paper mutations require enabling paper access |
| R3 — External action | Disabled |
For example, an agent can compare parameter cases and summarize the artifacts. It cannot infer permission to trade from having found an attractive historical result. These access levels are system boundaries, not an endorsement of any agent's research judgment.
Reproducibility means more than a random seed
seed = 42 can make a stochastic calculation repeatable. It does not identify the dataset, the factor definition, the strategy configuration or the information available at the decision time.
I need to answer a more practical question: can I explain what actually produced this decision? That requires the data snapshot, factor identity and version, parameters, strategy configuration and decision time to remain connected to the run. The generated artifacts and durable evidence need to be findable afterward.
Content identities and hashes help distinguish inputs that look similar but differ in substance. Receipts record operations and outcomes. Artifacts preserve outputs for inspection and comparison. They make it possible to trace a result back to its inputs rather than rely on a directory name such as final_run_2.
A hash identifies the content supplied; it does not prove that content is economically correct. Reproducing a flawed experiment remains a flawed experiment. Traceability makes the flaw easier to locate.
A synthetic end-to-end example
The public demo is a useful way to see these boundaries without connecting a data vendor or account. With Python 3.12 or later:
git clone https://github.com/Siyuan-chat/KabuForge.git
cd KabuForge
git checkout v0.1.0-rc.1
python -m pip install ".[gui]"
kabuforge doctor
kabuforge demo --out output/demo
kabuforge factors
kabuforge strategiesPinning the tag keeps this example tied to the release discussed here. doctor checks the local environment; the demo runs the bundled synthetic workflow; the final two commands expose the registered research units.
Actual output excerpt from the synthetic offline demo; the local output path is omitted:
{
"intents": 5,
"mode_intent_parity": true,
"submitted": false
}Conceptually, the demo takes synthetic data through factor calculation and strategy selection, forms a target, applies risk and planning, and writes backtest and paper-simulation artifacts. The useful observation is the connection between those stages and their outputs. A return curve from this input says nothing about investment performance.
The demo is offline. It requires no J-Quants API key, broker account, private factors or private market-data cache. Its output is an example of software behavior, not evidence of alpha. The code block is an excerpt of actual output from this tagged release, with the local output path omitted. The run produced five order intentions, reported intent parity across modes and did not submit orders. I have retained the generated plans as evidence; this check does not establish identical fills or market performance.
The current release boundary
| Capability | v0.1.0-rc.1 |
|---|---|
| Point-in-time-aware factor research | Available |
| Custom factor and strategy contracts | Available |
| Historical backtest | Available |
| Local paper simulation | Available |
| Broker-neutral order planning | Available |
| CLI | Available |
| Desktop GUI | Available |
| MCP / agent interface | Available |
| Broker protocol mappings / mocks | Validation layer |
| Real broker order submission | Not enabled |
“Available” describes a public software capability, not a guarantee that every configuration or dataset is suitable for use. KabuForge does not claim strategy profitability, alpha, market outperformance, live broker readiness or production trading readiness. It also does not claim complete historical PIT certification for all external data. This article is a technical explanation, not investment advice.
KabuForge is still an early project. v0.1.0-rc.1 is a release candidate. What I am trying to stabilize first is the research model: how information becomes a factor result, how that result becomes a portfolio decision, how the decision passes through risk and planning, and how the evidence remains inspectable when the operator is a human or an agent.
The implementation can grow around those boundaries.
Technical scope checked against the v0.1.0-rc.1 source and the public repository on 1 October 2026. See the implementation of factors, decisions, execution state and agent operations for details.