Skip to content

Commit 95a4a02

Browse files
committed
Initial runtime settings control plane
0 parents  commit 95a4a02

11 files changed

Lines changed: 826 additions & 0 deletions

File tree

.github/workflows/validate.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: Validate
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
jobs:
8+
validate:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v4
12+
- uses: actions/setup-python@v5
13+
with:
14+
python-version: "3.12"
15+
- name: Validate runtime targets
16+
run: python3 scripts/runtime_settings.py validate
17+
- name: Run unit tests
18+
run: python3 -m unittest discover -s tests -v
19+

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
__pycache__/
2+
.pytest_cache/
3+
.ruff_cache/
4+
.venv/
5+
local/

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 QuantStrategyLab
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# QuantRuntimeSettings
2+
3+
Declarative runtime settings tooling for QuantStrategyLab deployments.
4+
5+
This repository provides the schema and tooling for "which platform runs which strategy". It does not contain live runtime assignments, strategy logic, broker execution code, credentials, or secrets.
6+
7+
## Public Repository Policy
8+
9+
Live target files must not be committed to this public repository. Keep real deployment choices in GitHub Variables/Environments, GitHub Secrets, Secret Manager, or ignored local files under `local/`.
10+
11+
Use repository or environment variables for non-secret runtime choices such as `RUNTIME_TARGET_JSON` and plugin mount declarations. Use secrets only for credentials, tokens, and private keys.
12+
13+
If a deployment needs private validation policy, keep it in ignored local files such as `local/policy.json`.
14+
15+
## Boundaries
16+
17+
- `UsEquityStrategies` owns allocation logic, strategy defaults, and risk rules.
18+
- Platform repositories own broker adapters, runtime input collection, notifications, and execution.
19+
- This repository owns runtime target schemas, examples, validation, and rendering tools.
20+
- Secret values are intentionally excluded. Use secret names or platform repository secrets when needed.
21+
22+
## Commands
23+
24+
Validate examples, or local targets when `local/targets/**/*.json` exists:
25+
26+
```bash
27+
python3 scripts/runtime_settings.py validate
28+
```
29+
30+
Render assignments for an example:
31+
32+
```bash
33+
python3 scripts/runtime_settings.py render examples/targets/schwab/live.example.json
34+
```
35+
36+
Preview GitHub variable updates for an ignored local target:
37+
38+
```bash
39+
python3 scripts/runtime_settings.py apply local/targets/longbridge/sg.json
40+
```
41+
42+
Apply GitHub variable updates:
43+
44+
```bash
45+
python3 scripts/runtime_settings.py apply --yes local/targets/longbridge/sg.json
46+
```
47+
48+
`RUNTIME_TARGET_JSON` is canonical. Compatibility variables such as `STRATEGY_PROFILE` are generated from it so they cannot drift independently.
49+
50+
## Architecture
51+
52+
This repo acts as a small bridge between strategy selection and platform deployment without exposing live assignments:
53+
54+
- A target file declares the desired runtime target.
55+
- The validator checks that required runtime fields and plugin mounts are coherent.
56+
- Optional ignored local policy can add private strategy/plugin requirements.
57+
- The renderer converts the declaration into platform-specific GitHub variables.
58+
- Platform repositories keep their existing adapter code and consume the generated variables.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"$schema": "../../../schemas/runtime-target.schema.json",
3+
"target_id": "ibkr/default",
4+
"description": "Example Interactive Brokers deployment target.",
5+
"github": {
6+
"repository": "QuantStrategyLab/InteractiveBrokersPlatform",
7+
"variable_scope": "repository"
8+
},
9+
"runtime_target": {
10+
"platform_id": "ibkr",
11+
"strategy_profile": "example_strategy_profile",
12+
"dry_run_only": false,
13+
"deployment_selector": "example-default",
14+
"account_selector": ["example-default"],
15+
"account_scope": "example-default",
16+
"service_name": "example-ibkr-service",
17+
"execution_mode": "live"
18+
},
19+
"plugin_mounts_variable": "IBKR_STRATEGY_PLUGIN_MOUNTS_JSON",
20+
"plugin_mounts": [
21+
{
22+
"strategy": "example_strategy_profile",
23+
"plugin": "example_notification_plugin",
24+
"signal_path": "gs://example-bucket/strategy-artifacts/example_strategy_profile/plugins/example_notification_plugin/latest_signal.json",
25+
"enabled": true,
26+
"expected_mode": "shadow"
27+
}
28+
],
29+
"extra_variables": {}
30+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"$schema": "../../../schemas/runtime-target.schema.json",
3+
"target_id": "longbridge/sg",
4+
"description": "Example LongBridge environment-scoped deployment target.",
5+
"github": {
6+
"repository": "QuantStrategyLab/LongBridgePlatform",
7+
"variable_scope": "environment",
8+
"environment": "example-longbridge"
9+
},
10+
"runtime_target": {
11+
"platform_id": "longbridge",
12+
"strategy_profile": "example_strategy_profile",
13+
"dry_run_only": false,
14+
"deployment_selector": "EXAMPLE",
15+
"account_selector": ["EXAMPLE"],
16+
"account_scope": "EXAMPLE",
17+
"service_name": "example-longbridge-service",
18+
"execution_mode": "live"
19+
},
20+
"plugin_mounts_variable": "LONGBRIDGE_STRATEGY_PLUGIN_MOUNTS_JSON",
21+
"plugin_mounts": [
22+
{
23+
"strategy": "example_strategy_profile",
24+
"plugin": "example_notification_plugin",
25+
"signal_path": "gs://example-bucket/strategy-artifacts/example_strategy_profile/plugins/example_notification_plugin/latest_signal.json",
26+
"enabled": true,
27+
"expected_mode": "shadow"
28+
}
29+
],
30+
"extra_variables": {
31+
"LONGBRIDGE_DRY_RUN_ONLY": "false"
32+
}
33+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"$schema": "../../../schemas/runtime-target.schema.json",
3+
"target_id": "schwab/live",
4+
"description": "Example Charles Schwab live deployment target.",
5+
"github": {
6+
"repository": "QuantStrategyLab/CharlesSchwabPlatform",
7+
"variable_scope": "repository"
8+
},
9+
"runtime_target": {
10+
"platform_id": "schwab",
11+
"strategy_profile": "example_strategy_profile",
12+
"dry_run_only": false,
13+
"deployment_selector": "example-schwab",
14+
"account_selector": ["example-schwab"],
15+
"account_scope": "example-schwab",
16+
"service_name": "example-schwab-service",
17+
"execution_mode": "live"
18+
},
19+
"plugin_mounts_variable": "SCHWAB_STRATEGY_PLUGIN_MOUNTS_JSON",
20+
"plugin_mounts": [
21+
{
22+
"strategy": "example_strategy_profile",
23+
"plugin": "example_notification_plugin",
24+
"signal_path": "gs://example-bucket/strategy-artifacts/example_strategy_profile/plugins/example_notification_plugin/latest_signal.json",
25+
"enabled": true,
26+
"expected_mode": "shadow"
27+
}
28+
],
29+
"extra_variables": {}
30+
}

pyproject.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[project]
2+
name = "quant-runtime-settings"
3+
version = "0.1.0"
4+
description = "Declarative runtime target settings for QuantStrategyLab deployments"
5+
requires-python = ">=3.11"
6+
7+
[tool.ruff]
8+
line-length = 120
9+
target-version = "py311"
10+

schemas/runtime-target.schema.json

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"$id": "https://github.com/QuantStrategyLab/QuantRuntimeSettings/schemas/runtime-target.schema.json",
4+
"title": "Quant runtime target",
5+
"type": "object",
6+
"required": ["target_id", "github", "runtime_target"],
7+
"additionalProperties": false,
8+
"properties": {
9+
"$schema": {
10+
"type": "string"
11+
},
12+
"target_id": {
13+
"type": "string",
14+
"pattern": "^[a-z0-9_-]+/[a-z0-9_-]+$"
15+
},
16+
"description": {
17+
"type": "string"
18+
},
19+
"github": {
20+
"type": "object",
21+
"required": ["repository", "variable_scope"],
22+
"additionalProperties": false,
23+
"properties": {
24+
"repository": {
25+
"type": "string",
26+
"pattern": "^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$"
27+
},
28+
"variable_scope": {
29+
"type": "string",
30+
"enum": ["repository", "environment"]
31+
},
32+
"environment": {
33+
"type": "string"
34+
}
35+
}
36+
},
37+
"runtime_target": {
38+
"type": "object",
39+
"required": [
40+
"platform_id",
41+
"strategy_profile",
42+
"dry_run_only",
43+
"deployment_selector",
44+
"account_selector",
45+
"account_scope",
46+
"service_name",
47+
"execution_mode"
48+
],
49+
"additionalProperties": false,
50+
"properties": {
51+
"platform_id": {
52+
"type": "string"
53+
},
54+
"strategy_profile": {
55+
"type": "string"
56+
},
57+
"dry_run_only": {
58+
"type": "boolean"
59+
},
60+
"deployment_selector": {
61+
"type": "string"
62+
},
63+
"account_selector": {
64+
"type": "array",
65+
"items": {
66+
"type": "string"
67+
},
68+
"minItems": 1
69+
},
70+
"account_scope": {
71+
"type": "string"
72+
},
73+
"service_name": {
74+
"type": "string"
75+
},
76+
"execution_mode": {
77+
"type": "string",
78+
"enum": ["live", "paper", "dry_run"]
79+
}
80+
}
81+
},
82+
"plugin_mounts_variable": {
83+
"type": "string"
84+
},
85+
"plugin_mounts": {
86+
"type": "array",
87+
"items": {
88+
"type": "object",
89+
"required": ["strategy", "plugin", "signal_path", "enabled", "expected_mode"],
90+
"additionalProperties": false,
91+
"properties": {
92+
"strategy": {
93+
"type": "string"
94+
},
95+
"plugin": {
96+
"type": "string"
97+
},
98+
"signal_path": {
99+
"type": "string"
100+
},
101+
"enabled": {
102+
"type": "boolean"
103+
},
104+
"expected_mode": {
105+
"type": "string"
106+
}
107+
}
108+
}
109+
},
110+
"extra_variables": {
111+
"type": "object",
112+
"additionalProperties": {
113+
"type": ["string", "number", "integer", "boolean", "object", "array", "null"]
114+
}
115+
}
116+
}
117+
}
118+

0 commit comments

Comments
 (0)