autobrain-sim 1.0.0__tar.gz

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.
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2026
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1,6 @@
1
+ include README.md
2
+ include LICENSE
3
+ recursive-include examples *.py
4
+ exclude *.ipynb
5
+ recursive-exclude * __pycache__
6
+ recursive-exclude * *.py[cod]
@@ -0,0 +1,194 @@
1
+ Metadata-Version: 2.4
2
+ Name: autobrain-sim
3
+ Version: 1.0.0
4
+ Summary: Python client for the WorldQuant Brain API
5
+ Requires-Python: >=3.7
6
+ Description-Content-Type: text/markdown
7
+ License-File: LICENSE
8
+ Requires-Dist: requests>=2.28
9
+ Provides-Extra: dev
10
+ Requires-Dist: pytest; extra == "dev"
11
+ Requires-Dist: pytest-mock; extra == "dev"
12
+ Dynamic: license-file
13
+
14
+ # AutoBrain Sim
15
+
16
+ A lightweight Python client library for interacting with the [WorldQuant Brain](https://platform.worldquantbrain.com) platform API. Supports authentication, alpha simulation submission, and result retrieval.
17
+
18
+ ## Features
19
+
20
+ - Multiple authentication methods (direct, credentials file, interactive prompt)
21
+ - Submit alpha expressions for simulation
22
+ - Poll for simulation completion automatically
23
+ - Retrieve alpha details and PnL record sets
24
+
25
+ ## Install
26
+
27
+ ```bash
28
+ pip install autobrain-sim
29
+ ```
30
+
31
+ ## Requirements
32
+
33
+ - Python 3.7+
34
+ - `requests`
35
+
36
+ Install the dependency:
37
+
38
+ ```bash
39
+ pip install requests
40
+ ```
41
+
42
+ ## Files
43
+
44
+ | File | Description |
45
+ |------|-------------|
46
+ | `brain_client.py` | Core client library (`BrainClient`, `SimulationResult`) |
47
+ | `example.py` | Standalone usage example |
48
+ | `main.ipynb` | Jupyter notebook walkthrough |
49
+
50
+ ## Quick Start
51
+
52
+ ### Authentication
53
+
54
+ **Method 1 — Direct credentials**
55
+ ```python
56
+ from brain_client import BrainClient
57
+
58
+ client = BrainClient(email="your@email.com", password="yourpassword")
59
+ client.authenticate()
60
+ ```
61
+
62
+ **Method 2 — One-liner login**
63
+ ```python
64
+ client = BrainClient.login("your@email.com", "yourpassword")
65
+ ```
66
+
67
+ **Method 3 — Interactive prompt** (asks at runtime if no credentials are found)
68
+ ```python
69
+ client = BrainClient()
70
+ client.authenticate()
71
+ ```
72
+
73
+ **Method 4 — Credentials file**
74
+
75
+ Create `~/.brain_credentials` (or any path) as a JSON array:
76
+ ```json
77
+ ["your@email.com", "yourpassword"]
78
+ ```
79
+
80
+ Then load it:
81
+ ```python
82
+ client = BrainClient(credentials_file="~/.brain_credentials")
83
+ client.authenticate()
84
+ ```
85
+
86
+ > Credentials priority: direct args → `credentials_file` → `~/.brain_credentials` → interactive prompt.
87
+
88
+ ---
89
+
90
+ ### Simulate an Alpha
91
+
92
+ ```python
93
+ sim = client.simulate(
94
+ expression="close / ts_mean(close, 20) - 1",
95
+ settings={
96
+ "region": "USA",
97
+ "universe": "TOP3000",
98
+ "neutralization": "SUBINDUSTRY",
99
+ }
100
+ )
101
+
102
+ result = sim.wait(verbose=True) # blocks until done
103
+ print("Alpha ID:", sim.alpha_id)
104
+ ```
105
+
106
+ ### Retrieve Results
107
+
108
+ ```python
109
+ alpha = sim.get_alpha()
110
+ print("Sharpe:", alpha["is"]["sharpe"])
111
+ print("Fitness:", alpha["is"]["fitness"])
112
+
113
+ pnl = sim.get_pnl()
114
+ print(pnl)
115
+ ```
116
+
117
+ ---
118
+
119
+ ## API Reference
120
+
121
+ ### `BrainClient`
122
+
123
+ | Method | Description |
124
+ |--------|-------------|
125
+ | `__init__(email, password, credentials_file)` | Initialize client with credentials |
126
+ | `BrainClient.login(email, password)` | Create client and authenticate in one step |
127
+ | `authenticate()` | Sign in and obtain a session token |
128
+ | `simulate(expression, settings, ...)` | Submit an alpha for simulation; returns `SimulationResult` |
129
+ | `get_alpha(alpha_id)` | Fetch alpha details by ID |
130
+ | `get_pnl(alpha_id)` | Fetch PnL record set for an alpha |
131
+ | `get_recordset(alpha_id, record_set_name)` | Fetch any named record set |
132
+
133
+ #### Default Simulation Settings
134
+
135
+ ```python
136
+ {
137
+ "instrumentType": "EQUITY",
138
+ "region": "USA",
139
+ "universe": "TOP3000",
140
+ "delay": 1,
141
+ "decay": 15,
142
+ "neutralization": "SUBINDUSTRY",
143
+ "truncation": 0.08,
144
+ "maxTrade": "ON",
145
+ "pasteurization": "ON",
146
+ "testPeriod": "P1Y6M",
147
+ "unitHandling": "VERIFY",
148
+ "nanHandling": "OFF",
149
+ "language": "FASTEXPR",
150
+ }
151
+ ```
152
+
153
+ Any key passed via `settings` overrides the default.
154
+
155
+ ---
156
+
157
+ ### `SimulationResult`
158
+
159
+ Returned by `client.simulate()`.
160
+
161
+ | Method | Description |
162
+ |--------|-------------|
163
+ | `wait(verbose=True)` | Poll until simulation completes; returns result JSON |
164
+ | `get_alpha()` | Fetch full alpha details (call after `wait()`) |
165
+ | `get_pnl(poll_interval)` | Fetch PnL record set (call after `wait()`) |
166
+
167
+ | Attribute | Description |
168
+ |-----------|-------------|
169
+ | `alpha_id` | Alpha ID string (available after `wait()`) |
170
+ | `progress_url` | URL used to poll simulation progress |
171
+
172
+ ---
173
+
174
+ ## Example
175
+
176
+ ```python
177
+ from brain_client import BrainClient
178
+
179
+ client = BrainClient.login() # interactive prompt
180
+
181
+ sim = client.simulate("close / ts_mean(close, 20) - 1")
182
+ result = sim.wait(verbose=True)
183
+
184
+ alpha = sim.get_alpha()
185
+ print(f"Alpha ID : {sim.alpha_id}")
186
+ print(f"Sharpe : {alpha['is']['sharpe']}")
187
+ print(f"Fitness : {alpha['is']['fitness']}")
188
+ ```
189
+
190
+ ## Notes
191
+
192
+ - The client uses HTTP Basic Auth to obtain a session token from the `/authentication` endpoint.
193
+ - Polling respects the `Retry-After` response header returned by the Brain API.
194
+ - Never commit your credentials to version control. Use `~/.brain_credentials` or environment variables instead.
@@ -0,0 +1,181 @@
1
+ # AutoBrain Sim
2
+
3
+ A lightweight Python client library for interacting with the [WorldQuant Brain](https://platform.worldquantbrain.com) platform API. Supports authentication, alpha simulation submission, and result retrieval.
4
+
5
+ ## Features
6
+
7
+ - Multiple authentication methods (direct, credentials file, interactive prompt)
8
+ - Submit alpha expressions for simulation
9
+ - Poll for simulation completion automatically
10
+ - Retrieve alpha details and PnL record sets
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ pip install autobrain-sim
16
+ ```
17
+
18
+ ## Requirements
19
+
20
+ - Python 3.7+
21
+ - `requests`
22
+
23
+ Install the dependency:
24
+
25
+ ```bash
26
+ pip install requests
27
+ ```
28
+
29
+ ## Files
30
+
31
+ | File | Description |
32
+ |------|-------------|
33
+ | `brain_client.py` | Core client library (`BrainClient`, `SimulationResult`) |
34
+ | `example.py` | Standalone usage example |
35
+ | `main.ipynb` | Jupyter notebook walkthrough |
36
+
37
+ ## Quick Start
38
+
39
+ ### Authentication
40
+
41
+ **Method 1 — Direct credentials**
42
+ ```python
43
+ from brain_client import BrainClient
44
+
45
+ client = BrainClient(email="your@email.com", password="yourpassword")
46
+ client.authenticate()
47
+ ```
48
+
49
+ **Method 2 — One-liner login**
50
+ ```python
51
+ client = BrainClient.login("your@email.com", "yourpassword")
52
+ ```
53
+
54
+ **Method 3 — Interactive prompt** (asks at runtime if no credentials are found)
55
+ ```python
56
+ client = BrainClient()
57
+ client.authenticate()
58
+ ```
59
+
60
+ **Method 4 — Credentials file**
61
+
62
+ Create `~/.brain_credentials` (or any path) as a JSON array:
63
+ ```json
64
+ ["your@email.com", "yourpassword"]
65
+ ```
66
+
67
+ Then load it:
68
+ ```python
69
+ client = BrainClient(credentials_file="~/.brain_credentials")
70
+ client.authenticate()
71
+ ```
72
+
73
+ > Credentials priority: direct args → `credentials_file` → `~/.brain_credentials` → interactive prompt.
74
+
75
+ ---
76
+
77
+ ### Simulate an Alpha
78
+
79
+ ```python
80
+ sim = client.simulate(
81
+ expression="close / ts_mean(close, 20) - 1",
82
+ settings={
83
+ "region": "USA",
84
+ "universe": "TOP3000",
85
+ "neutralization": "SUBINDUSTRY",
86
+ }
87
+ )
88
+
89
+ result = sim.wait(verbose=True) # blocks until done
90
+ print("Alpha ID:", sim.alpha_id)
91
+ ```
92
+
93
+ ### Retrieve Results
94
+
95
+ ```python
96
+ alpha = sim.get_alpha()
97
+ print("Sharpe:", alpha["is"]["sharpe"])
98
+ print("Fitness:", alpha["is"]["fitness"])
99
+
100
+ pnl = sim.get_pnl()
101
+ print(pnl)
102
+ ```
103
+
104
+ ---
105
+
106
+ ## API Reference
107
+
108
+ ### `BrainClient`
109
+
110
+ | Method | Description |
111
+ |--------|-------------|
112
+ | `__init__(email, password, credentials_file)` | Initialize client with credentials |
113
+ | `BrainClient.login(email, password)` | Create client and authenticate in one step |
114
+ | `authenticate()` | Sign in and obtain a session token |
115
+ | `simulate(expression, settings, ...)` | Submit an alpha for simulation; returns `SimulationResult` |
116
+ | `get_alpha(alpha_id)` | Fetch alpha details by ID |
117
+ | `get_pnl(alpha_id)` | Fetch PnL record set for an alpha |
118
+ | `get_recordset(alpha_id, record_set_name)` | Fetch any named record set |
119
+
120
+ #### Default Simulation Settings
121
+
122
+ ```python
123
+ {
124
+ "instrumentType": "EQUITY",
125
+ "region": "USA",
126
+ "universe": "TOP3000",
127
+ "delay": 1,
128
+ "decay": 15,
129
+ "neutralization": "SUBINDUSTRY",
130
+ "truncation": 0.08,
131
+ "maxTrade": "ON",
132
+ "pasteurization": "ON",
133
+ "testPeriod": "P1Y6M",
134
+ "unitHandling": "VERIFY",
135
+ "nanHandling": "OFF",
136
+ "language": "FASTEXPR",
137
+ }
138
+ ```
139
+
140
+ Any key passed via `settings` overrides the default.
141
+
142
+ ---
143
+
144
+ ### `SimulationResult`
145
+
146
+ Returned by `client.simulate()`.
147
+
148
+ | Method | Description |
149
+ |--------|-------------|
150
+ | `wait(verbose=True)` | Poll until simulation completes; returns result JSON |
151
+ | `get_alpha()` | Fetch full alpha details (call after `wait()`) |
152
+ | `get_pnl(poll_interval)` | Fetch PnL record set (call after `wait()`) |
153
+
154
+ | Attribute | Description |
155
+ |-----------|-------------|
156
+ | `alpha_id` | Alpha ID string (available after `wait()`) |
157
+ | `progress_url` | URL used to poll simulation progress |
158
+
159
+ ---
160
+
161
+ ## Example
162
+
163
+ ```python
164
+ from brain_client import BrainClient
165
+
166
+ client = BrainClient.login() # interactive prompt
167
+
168
+ sim = client.simulate("close / ts_mean(close, 20) - 1")
169
+ result = sim.wait(verbose=True)
170
+
171
+ alpha = sim.get_alpha()
172
+ print(f"Alpha ID : {sim.alpha_id}")
173
+ print(f"Sharpe : {alpha['is']['sharpe']}")
174
+ print(f"Fitness : {alpha['is']['fitness']}")
175
+ ```
176
+
177
+ ## Notes
178
+
179
+ - The client uses HTTP Basic Auth to obtain a session token from the `/authentication` endpoint.
180
+ - Polling respects the `Retry-After` response header returned by the Brain API.
181
+ - Never commit your credentials to version control. Use `~/.brain_credentials` or environment variables instead.
@@ -0,0 +1,194 @@
1
+ Metadata-Version: 2.4
2
+ Name: autobrain-sim
3
+ Version: 1.0.0
4
+ Summary: Python client for the WorldQuant Brain API
5
+ Requires-Python: >=3.7
6
+ Description-Content-Type: text/markdown
7
+ License-File: LICENSE
8
+ Requires-Dist: requests>=2.28
9
+ Provides-Extra: dev
10
+ Requires-Dist: pytest; extra == "dev"
11
+ Requires-Dist: pytest-mock; extra == "dev"
12
+ Dynamic: license-file
13
+
14
+ # AutoBrain Sim
15
+
16
+ A lightweight Python client library for interacting with the [WorldQuant Brain](https://platform.worldquantbrain.com) platform API. Supports authentication, alpha simulation submission, and result retrieval.
17
+
18
+ ## Features
19
+
20
+ - Multiple authentication methods (direct, credentials file, interactive prompt)
21
+ - Submit alpha expressions for simulation
22
+ - Poll for simulation completion automatically
23
+ - Retrieve alpha details and PnL record sets
24
+
25
+ ## Install
26
+
27
+ ```bash
28
+ pip install autobrain-sim
29
+ ```
30
+
31
+ ## Requirements
32
+
33
+ - Python 3.7+
34
+ - `requests`
35
+
36
+ Install the dependency:
37
+
38
+ ```bash
39
+ pip install requests
40
+ ```
41
+
42
+ ## Files
43
+
44
+ | File | Description |
45
+ |------|-------------|
46
+ | `brain_client.py` | Core client library (`BrainClient`, `SimulationResult`) |
47
+ | `example.py` | Standalone usage example |
48
+ | `main.ipynb` | Jupyter notebook walkthrough |
49
+
50
+ ## Quick Start
51
+
52
+ ### Authentication
53
+
54
+ **Method 1 — Direct credentials**
55
+ ```python
56
+ from brain_client import BrainClient
57
+
58
+ client = BrainClient(email="your@email.com", password="yourpassword")
59
+ client.authenticate()
60
+ ```
61
+
62
+ **Method 2 — One-liner login**
63
+ ```python
64
+ client = BrainClient.login("your@email.com", "yourpassword")
65
+ ```
66
+
67
+ **Method 3 — Interactive prompt** (asks at runtime if no credentials are found)
68
+ ```python
69
+ client = BrainClient()
70
+ client.authenticate()
71
+ ```
72
+
73
+ **Method 4 — Credentials file**
74
+
75
+ Create `~/.brain_credentials` (or any path) as a JSON array:
76
+ ```json
77
+ ["your@email.com", "yourpassword"]
78
+ ```
79
+
80
+ Then load it:
81
+ ```python
82
+ client = BrainClient(credentials_file="~/.brain_credentials")
83
+ client.authenticate()
84
+ ```
85
+
86
+ > Credentials priority: direct args → `credentials_file` → `~/.brain_credentials` → interactive prompt.
87
+
88
+ ---
89
+
90
+ ### Simulate an Alpha
91
+
92
+ ```python
93
+ sim = client.simulate(
94
+ expression="close / ts_mean(close, 20) - 1",
95
+ settings={
96
+ "region": "USA",
97
+ "universe": "TOP3000",
98
+ "neutralization": "SUBINDUSTRY",
99
+ }
100
+ )
101
+
102
+ result = sim.wait(verbose=True) # blocks until done
103
+ print("Alpha ID:", sim.alpha_id)
104
+ ```
105
+
106
+ ### Retrieve Results
107
+
108
+ ```python
109
+ alpha = sim.get_alpha()
110
+ print("Sharpe:", alpha["is"]["sharpe"])
111
+ print("Fitness:", alpha["is"]["fitness"])
112
+
113
+ pnl = sim.get_pnl()
114
+ print(pnl)
115
+ ```
116
+
117
+ ---
118
+
119
+ ## API Reference
120
+
121
+ ### `BrainClient`
122
+
123
+ | Method | Description |
124
+ |--------|-------------|
125
+ | `__init__(email, password, credentials_file)` | Initialize client with credentials |
126
+ | `BrainClient.login(email, password)` | Create client and authenticate in one step |
127
+ | `authenticate()` | Sign in and obtain a session token |
128
+ | `simulate(expression, settings, ...)` | Submit an alpha for simulation; returns `SimulationResult` |
129
+ | `get_alpha(alpha_id)` | Fetch alpha details by ID |
130
+ | `get_pnl(alpha_id)` | Fetch PnL record set for an alpha |
131
+ | `get_recordset(alpha_id, record_set_name)` | Fetch any named record set |
132
+
133
+ #### Default Simulation Settings
134
+
135
+ ```python
136
+ {
137
+ "instrumentType": "EQUITY",
138
+ "region": "USA",
139
+ "universe": "TOP3000",
140
+ "delay": 1,
141
+ "decay": 15,
142
+ "neutralization": "SUBINDUSTRY",
143
+ "truncation": 0.08,
144
+ "maxTrade": "ON",
145
+ "pasteurization": "ON",
146
+ "testPeriod": "P1Y6M",
147
+ "unitHandling": "VERIFY",
148
+ "nanHandling": "OFF",
149
+ "language": "FASTEXPR",
150
+ }
151
+ ```
152
+
153
+ Any key passed via `settings` overrides the default.
154
+
155
+ ---
156
+
157
+ ### `SimulationResult`
158
+
159
+ Returned by `client.simulate()`.
160
+
161
+ | Method | Description |
162
+ |--------|-------------|
163
+ | `wait(verbose=True)` | Poll until simulation completes; returns result JSON |
164
+ | `get_alpha()` | Fetch full alpha details (call after `wait()`) |
165
+ | `get_pnl(poll_interval)` | Fetch PnL record set (call after `wait()`) |
166
+
167
+ | Attribute | Description |
168
+ |-----------|-------------|
169
+ | `alpha_id` | Alpha ID string (available after `wait()`) |
170
+ | `progress_url` | URL used to poll simulation progress |
171
+
172
+ ---
173
+
174
+ ## Example
175
+
176
+ ```python
177
+ from brain_client import BrainClient
178
+
179
+ client = BrainClient.login() # interactive prompt
180
+
181
+ sim = client.simulate("close / ts_mean(close, 20) - 1")
182
+ result = sim.wait(verbose=True)
183
+
184
+ alpha = sim.get_alpha()
185
+ print(f"Alpha ID : {sim.alpha_id}")
186
+ print(f"Sharpe : {alpha['is']['sharpe']}")
187
+ print(f"Fitness : {alpha['is']['fitness']}")
188
+ ```
189
+
190
+ ## Notes
191
+
192
+ - The client uses HTTP Basic Auth to obtain a session token from the `/authentication` endpoint.
193
+ - Polling respects the `Retry-After` response header returned by the Brain API.
194
+ - Never commit your credentials to version control. Use `~/.brain_credentials` or environment variables instead.
@@ -0,0 +1,11 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ brain_client.py
5
+ pyproject.toml
6
+ autobrain_sim.egg-info/PKG-INFO
7
+ autobrain_sim.egg-info/SOURCES.txt
8
+ autobrain_sim.egg-info/dependency_links.txt
9
+ autobrain_sim.egg-info/requires.txt
10
+ autobrain_sim.egg-info/top_level.txt
11
+ examples/example.py
@@ -0,0 +1,5 @@
1
+ requests>=2.28
2
+
3
+ [dev]
4
+ pytest
5
+ pytest-mock
@@ -0,0 +1 @@
1
+ brain_client
@@ -0,0 +1,282 @@
1
+ """
2
+ WorldQuant Brain API Client Library
3
+
4
+ A Python client for interacting with the WorldQuant Brain platform API.
5
+ Supports authentication, alpha simulation, and result retrieval.
6
+ """
7
+
8
+ import json
9
+ import getpass
10
+ import requests
11
+ from time import sleep
12
+ from os.path import expanduser
13
+ from typing import Optional
14
+
15
+
16
+ BASE_URL = "https://api.worldquantbrain.com"
17
+
18
+
19
+ class BrainClient:
20
+ """Client for the WorldQuant Brain API."""
21
+
22
+ def __init__(
23
+ self,
24
+ email: Optional[str] = None,
25
+ password: Optional[str] = None,
26
+ credentials_file: Optional[str] = None,
27
+ ):
28
+ """
29
+ Initialize the client. Credentials priority:
30
+ 1. email + password passed directly
31
+ 2. credentials_file path (JSON: ["email", "password"])
32
+ 3. ~/.brain_credentials (if the file exists)
33
+ 4. Interactive prompt (asks at runtime)
34
+
35
+ Args:
36
+ email: Brain platform email.
37
+ password: Brain platform password.
38
+ credentials_file: Path to a JSON credentials file.
39
+ """
40
+ self._session = requests.Session()
41
+ self._authenticated = False
42
+
43
+ if email and password:
44
+ self._session.auth = (email, password)
45
+ return
46
+
47
+ if credentials_file:
48
+ with open(expanduser(credentials_file), "r") as f:
49
+ self._session.auth = tuple(json.load(f))
50
+ return
51
+
52
+ default_file = expanduser("~/.brain_credentials")
53
+ try:
54
+ with open(default_file, "r") as f:
55
+ self._session.auth = tuple(json.load(f))
56
+ except FileNotFoundError:
57
+ # Fall back to interactive prompt
58
+ email = input("WorldQuant Brain email: ").strip()
59
+ password = getpass.getpass("WorldQuant Brain password: ")
60
+ self._session.auth = (email, password)
61
+
62
+ @classmethod
63
+ def login(cls, email: Optional[str] = None, password: Optional[str] = None) -> "BrainClient":
64
+ """
65
+ Create a BrainClient and authenticate in one step.
66
+
67
+ If email/password are not provided, prompts interactively.
68
+
69
+ Args:
70
+ email: Brain platform email (optional).
71
+ password: Brain platform password (optional).
72
+
73
+ Returns:
74
+ An authenticated BrainClient instance.
75
+
76
+ Example:
77
+ client = BrainClient.login() # interactive prompt
78
+ client = BrainClient.login("me@email.com", "pass") # direct
79
+ """
80
+ client = cls(email=email, password=password)
81
+ client.authenticate()
82
+ return client
83
+
84
+ # -------------------------------------------------------------------------
85
+ # Authentication
86
+ # -------------------------------------------------------------------------
87
+
88
+ def authenticate(self) -> dict:
89
+ """
90
+ Sign in and obtain a JWT token.
91
+
92
+ Returns:
93
+ Response JSON from the /authentication endpoint.
94
+
95
+ Raises:
96
+ requests.HTTPError: If authentication fails.
97
+ """
98
+ response = self._session.post(f"{BASE_URL}/authentication")
99
+ response.raise_for_status()
100
+ self._authenticated = True
101
+ return response.json()
102
+
103
+ # -------------------------------------------------------------------------
104
+ # Simulations
105
+ # -------------------------------------------------------------------------
106
+
107
+ def simulate(self, expression: str, settings: dict = None, alpha_type: str = "REGULAR", regular: str = "close") -> "SimulationResult":
108
+ """
109
+ Submit an alpha expression for simulation.
110
+
111
+ Args:
112
+ expression: The alpha expression string.
113
+ settings: Simulation settings dict. Defaults to standard equity settings.
114
+ alpha_type: Type of simulation, e.g. "REGULAR".
115
+ regular: Price field, e.g. "close".
116
+
117
+ Returns:
118
+ A SimulationResult object to poll for completion.
119
+
120
+ Raises:
121
+ requests.HTTPError: If the submission fails.
122
+ """
123
+ default_settings = {
124
+ "instrumentType": "EQUITY",
125
+ "region": "USA",
126
+ "universe": "TOP3000",
127
+ "delay": 1,
128
+ "decay": 15,
129
+ "neutralization": "SUBINDUSTRY",
130
+ "truncation": 0.08,
131
+ "maxTrade": "ON",
132
+ "pasteurization": "ON",
133
+ "testPeriod": "P1Y6M",
134
+ "unitHandling": "VERIFY",
135
+ "nanHandling": "OFF",
136
+ "language": "FASTEXPR",
137
+ "visualization": False,
138
+ }
139
+ if settings:
140
+ default_settings.update(settings)
141
+
142
+ payload = {
143
+ "type": alpha_type,
144
+ "settings": default_settings,
145
+ "regular": expression if regular == "close" else regular,
146
+ }
147
+
148
+ # If expression is provided separately from regular field
149
+ if regular == "close":
150
+ payload["regular"] = expression
151
+
152
+ response = self._session.post(f"{BASE_URL}/simulations", json=payload)
153
+ response.raise_for_status()
154
+
155
+ progress_url = response.headers.get("Location")
156
+ return SimulationResult(self._session, progress_url)
157
+
158
+ # -------------------------------------------------------------------------
159
+ # Alphas
160
+ # -------------------------------------------------------------------------
161
+
162
+ def get_alpha(self, alpha_id: str) -> dict:
163
+ """
164
+ Retrieve details of a completed alpha by ID.
165
+
166
+ Args:
167
+ alpha_id: The alpha ID string.
168
+
169
+ Returns:
170
+ Alpha details as a dict.
171
+ """
172
+ response = self._session.get(f"{BASE_URL}/alphas/{alpha_id}")
173
+ response.raise_for_status()
174
+ return response.json()
175
+
176
+ def get_pnl(self, alpha_id: str, poll_interval: float = 5.0) -> dict:
177
+ """
178
+ Retrieve PnL record set for an alpha, polling until ready.
179
+
180
+ Args:
181
+ alpha_id: The alpha ID string.
182
+ poll_interval: Fallback seconds to wait between polls if no Retry-After header.
183
+
184
+ Returns:
185
+ PnL record set as a dict.
186
+ """
187
+ return self._poll_recordset(alpha_id, "pnl", poll_interval)
188
+
189
+ def get_recordset(self, alpha_id: str, record_set_name: str, poll_interval: float = 5.0) -> dict:
190
+ """
191
+ Retrieve any named record set for an alpha, polling until ready.
192
+
193
+ Args:
194
+ alpha_id: The alpha ID string.
195
+ record_set_name: Name of the record set (e.g. "pnl", "sharpe").
196
+ poll_interval: Fallback seconds between polls if no Retry-After header.
197
+
198
+ Returns:
199
+ Record set data as a dict.
200
+ """
201
+ return self._poll_recordset(alpha_id, record_set_name, poll_interval)
202
+
203
+ def _poll_recordset(self, alpha_id: str, record_set_name: str, poll_interval: float) -> dict:
204
+ url = f"{BASE_URL}/alphas/{alpha_id}/recordsets/{record_set_name}"
205
+ while True:
206
+ response = self._session.get(url)
207
+ retry_after = float(response.headers.get("Retry-After", 0))
208
+ if retry_after == 0:
209
+ response.raise_for_status()
210
+ return response.json()
211
+ #print(f"Sleeping for {retry_after} seconds...")
212
+ sleep(retry_after)
213
+
214
+
215
+ class SimulationResult:
216
+ """Represents a pending or completed alpha simulation."""
217
+
218
+ def __init__(self, session: requests.Session, progress_url: str):
219
+ self._session = session
220
+ self.progress_url = progress_url
221
+ self.alpha_id: str = None
222
+ self._result: dict = None
223
+
224
+ def wait(self, verbose: bool = True) -> dict:
225
+ """
226
+ Poll until the simulation completes.
227
+
228
+ Args:
229
+ verbose: If True, print polling status messages.
230
+
231
+ Returns:
232
+ The completed simulation result JSON containing the alpha id.
233
+ """
234
+ while True:
235
+ response = self._session.get(self.progress_url)
236
+ retry_after = float(response.headers.get("Retry-After", 0))
237
+ if retry_after == 0:
238
+ response.raise_for_status()
239
+ self._result = response.json()
240
+ self.alpha_id = self._result.get("alpha")
241
+ if verbose:
242
+ print(f"Alpha simulation complete. Alpha ID: {self.alpha_id}")
243
+ return self._result
244
+ if verbose:
245
+ print(f"Simulating... sleeping for {retry_after} seconds")
246
+ sleep(retry_after)
247
+
248
+ def get_alpha(self) -> dict:
249
+ """
250
+ Fetch full alpha details after simulation completes.
251
+
252
+ Returns:
253
+ Alpha details dict.
254
+
255
+ Raises:
256
+ RuntimeError: If wait() has not been called yet.
257
+ """
258
+ if not self.alpha_id:
259
+ raise RuntimeError("Simulation not complete. Call wait() first.")
260
+ response = self._session.get(f"{BASE_URL}/alphas/{self.alpha_id}")
261
+ response.raise_for_status()
262
+ return response.json()
263
+
264
+ def get_pnl(self, poll_interval: float = 5.0) -> dict:
265
+ """
266
+ Retrieve PnL record set after simulation completes.
267
+
268
+ Args:
269
+ poll_interval: Fallback seconds between polls if no Retry-After header.
270
+
271
+ Returns:
272
+ PnL record set dict.
273
+
274
+ Raises:
275
+ RuntimeError: If wait() has not been called yet.
276
+ """
277
+ if not self.alpha_id:
278
+ raise RuntimeError("Simulation not complete. Call wait() first.")
279
+ client = BrainClient.__new__(BrainClient)
280
+ client._session = self._session
281
+ client._authenticated = True
282
+ return client.get_pnl(self.alpha_id, poll_interval)
@@ -0,0 +1,40 @@
1
+ """
2
+ Example usage of the WorldQuant Brain API client library.
3
+ """
4
+
5
+ from brain_client import BrainClient
6
+
7
+ # ── วิธีที่ 1: ใส่ email/password โดยตรง ────────────────────────────────────
8
+ client = BrainClient(email="your@email.com", password="yourpassword")
9
+ client.authenticate()
10
+
11
+ # ── วิธีที่ 2: Interactive prompt (ถามตอนรัน) ────────────────────────────────
12
+ # client = BrainClient() # ถ้าไม่มี ~/.brain_credentials จะ prompt อัตโนมัติ
13
+ # client.authenticate()
14
+
15
+ # ── วิธีที่ 3: login() — สั้นสุด สร้าง + auth ในบรรทัดเดียว ─────────────────
16
+ # client = BrainClient.login() # interactive prompt
17
+ # client = BrainClient.login("your@email.com", "pass") # หรือใส่ตรงๆ
18
+
19
+ # ── วิธีที่ 4: Credentials file ──────────────────────────────────────────────
20
+ # client = BrainClient(credentials_file="~/my_creds.json")
21
+ # client.authenticate()
22
+
23
+ print("Authenticated!")
24
+
25
+ # Submit simulation
26
+ sim = client.simulate(
27
+ expression="close / ts_mean(close, 20) - 1",
28
+ settings={
29
+ "region": "USA",
30
+ "universe": "TOP3000",
31
+ "neutralization": "SUBINDUSTRY",
32
+ }
33
+ )
34
+
35
+ result = sim.wait(verbose=True)
36
+ print("Alpha ID:", sim.alpha_id)
37
+
38
+ alpha = sim.get_alpha()
39
+ print("Sharpe:", alpha["is"]["sharpe"])
40
+ print("Fitness:", alpha["is"]["fitness"])
@@ -0,0 +1,23 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "autobrain-sim"
7
+ version = "1.0.0"
8
+ description = "Python client for the WorldQuant Brain API"
9
+ readme = "README.md"
10
+ requires-python = ">=3.7"
11
+
12
+ dependencies = [
13
+ "requests>=2.28",
14
+ ]
15
+
16
+ [project.optional-dependencies]
17
+ dev = [
18
+ "pytest",
19
+ "pytest-mock",
20
+ ]
21
+
22
+ [tool.setuptools]
23
+ py-modules = ["brain_client"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+