simudyne-pulse 0.7.0.dev5__tar.gz → 0.7.0.dev6__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.
Files changed (28) hide show
  1. {simudyne_pulse-0.7.0.dev5/src/simudyne_pulse.egg-info → simudyne_pulse-0.7.0.dev6}/PKG-INFO +1 -1
  2. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/pyproject.toml +1 -1
  3. simudyne_pulse-0.7.0.dev6/src/simudyne/resources/api_keys.py +83 -0
  4. simudyne_pulse-0.7.0.dev6/src/simudyne/resources/profile.py +103 -0
  5. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/src/simudyne/resources/validation.py +118 -8
  6. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6/src/simudyne_pulse.egg-info}/PKG-INFO +1 -1
  7. simudyne_pulse-0.7.0.dev5/src/simudyne/resources/api_keys.py +0 -12
  8. simudyne_pulse-0.7.0.dev5/src/simudyne/resources/profile.py +0 -30
  9. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/LICENSE +0 -0
  10. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/README.md +0 -0
  11. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/setup.cfg +0 -0
  12. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/src/simudyne/__init__.py +0 -0
  13. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/src/simudyne/client.py +0 -0
  14. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/src/simudyne/exceptions.py +0 -0
  15. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/src/simudyne/resources/__init__.py +0 -0
  16. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/src/simudyne/resources/data.py +0 -0
  17. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/src/simudyne/resources/fix.py +0 -0
  18. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/src/simudyne/resources/fm.py +0 -0
  19. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/src/simudyne/resources/historical.py +0 -0
  20. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/src/simudyne/resources/simulation.py +0 -0
  21. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/src/simudyne/resources/simulator_gym.py +0 -0
  22. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/src/simudyne_pulse.egg-info/SOURCES.txt +0 -0
  23. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/src/simudyne_pulse.egg-info/dependency_links.txt +0 -0
  24. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/src/simudyne_pulse.egg-info/requires.txt +0 -0
  25. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/src/simudyne_pulse.egg-info/top_level.txt +0 -0
  26. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/tests/test_new_resources.py +0 -0
  27. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/tests/test_simulator_gym.py +0 -0
  28. {simudyne_pulse-0.7.0.dev5 → simudyne_pulse-0.7.0.dev6}/tests/test_validation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simudyne-pulse
3
- Version: 0.7.0.dev5
3
+ Version: 0.7.0.dev6
4
4
  Summary: Python SDK for the Simudyne Pulse synthetic market data API
5
5
  Author-email: Simudyne <support@simudyne.com>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "simudyne-pulse"
7
- version = "0.7.0-dev.5"
7
+ version = "0.7.0-dev.6"
8
8
  description = "Python SDK for the Simudyne Pulse synthetic market data API"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -0,0 +1,83 @@
1
+ class ApiKeysResource:
2
+ def __init__(self, client):
3
+ self._client = client
4
+
5
+ def create(self, name: str):
6
+ """Mint a new API key.
7
+
8
+ The only call that ever returns the key material. It is shown once —
9
+ store it before the call returns, or mint another.
10
+
11
+ Parameters
12
+ ----------
13
+ name : str
14
+ A label for the key. Name it by purpose ("notebook",
15
+ "production", "CI pipeline") so you know which to revoke if one
16
+ is compromised.
17
+
18
+ Returns
19
+ -------
20
+ dict
21
+ api_key : str
22
+ The key material, shown exactly once.
23
+ api_key_id : str
24
+ The handle to pass to :meth:`revoke`.
25
+ warning : str
26
+ A reminder that the key will not be shown again.
27
+
28
+ Examples
29
+ --------
30
+ >>> new_key = client.api_keys.create(name="Training script")
31
+ >>> print(new_key["api_key"]) # save this, it won't be shown again
32
+ """
33
+ return self._client._request("POST", "/api-keys", json={"name": name})
34
+
35
+ def list(self):
36
+ """List your active API keys and their labels.
37
+
38
+ The full key is never returned after creation; only ``key_prefix``,
39
+ the first 12 characters, is stored. That is enough to tell keys apart
40
+ and not enough to reconstruct one.
41
+
42
+ Returns
43
+ -------
44
+ list of dict
45
+ One entry per key, each with:
46
+
47
+ - api_key_id (str): the handle to pass to :meth:`revoke`
48
+ - key_prefix (str): first 12 characters, e.g. "pk_live_ab12"
49
+ - name (str): the label you gave it
50
+ - is_active (bool): False once revoked
51
+ - created_at (str): when it was created
52
+ - last_used_at (str or None): None until the key is first used
53
+ - expires_at (str or None): None for keys that do not expire
54
+
55
+ Examples
56
+ --------
57
+ >>> for key in client.api_keys.list():
58
+ ... print(key["name"], key["key_prefix"], key["created_at"])
59
+ """
60
+ return self._client._request("GET", "/api-keys")
61
+
62
+ def revoke(self, key_id: str):
63
+ """Invalidate a key immediately.
64
+
65
+ Any request still using the key returns HTTP 401 from this point on.
66
+
67
+ Parameters
68
+ ----------
69
+ key_id : str
70
+ The ``api_key_id`` from :meth:`list` or :meth:`create` — not the
71
+ key material itself.
72
+
73
+ Returns
74
+ -------
75
+ dict
76
+ The revocation result.
77
+
78
+ Examples
79
+ --------
80
+ >>> new_key = client.api_keys.create(name="Training script")
81
+ >>> client.api_keys.revoke(key_id=new_key["api_key_id"])
82
+ """
83
+ return self._client._request("DELETE", f"/api-keys/{key_id}")
@@ -0,0 +1,103 @@
1
+ class ProfileResource:
2
+ def __init__(self, client):
3
+ self._client = client
4
+
5
+ def get(self):
6
+ """Return your account record.
7
+
8
+ The cheapest way to confirm a key works and to find out which tier it
9
+ is on — worth calling first when a 403 surprises you.
10
+
11
+ Returns
12
+ -------
13
+ dict
14
+ user_id : str
15
+ Your account id. Also your FIX CompID, where FIX is enabled.
16
+ email : str
17
+ The address the account was created with.
18
+ name : str
19
+ Display name.
20
+ organization : str
21
+ Organisation, empty string if never set.
22
+ is_admin : bool
23
+ Administrative flag governing user administration, not
24
+ simulator access. It is not a tier bypass: an admin flag on a
25
+ free-tier key still cannot run a simulation. When a call
26
+ returns 403, read ``tier``, not this.
27
+ tier : {"free", "pro", "demo"}
28
+ What gates every endpoint.
29
+ download_limit : int
30
+ New simulation groups per rolling 24 hours. Only enforced on
31
+ the free tier.
32
+
33
+ Examples
34
+ --------
35
+ >>> me = client.profile.get()
36
+ >>> print(f"{me['email']} — tier {me['tier']}")
37
+ """
38
+ return self._client._request("GET", "/profile")
39
+
40
+ def usage(self):
41
+ """Return your request count for the current calendar month.
42
+
43
+ Resets on the 1st, and counts *requests* rather than simulations —
44
+ one ``run()`` of 100 Monte Carlo runs is a single request here.
45
+
46
+ Returns
47
+ -------
48
+ dict
49
+ user_id : str
50
+ Your account id.
51
+ month : str
52
+ The calendar month being reported, "YYYY-MM".
53
+ total_requests : int
54
+ Requests so far this month.
55
+ by_endpoint : dict
56
+ Request count keyed by endpoint path. The keys are the
57
+ concrete paths that were called, so a job-scoped endpoint
58
+ appears once per job id rather than as a template — aggregate
59
+ by prefix if you want per-endpoint totals.
60
+
61
+ Examples
62
+ --------
63
+ >>> usage = client.profile.usage()
64
+ >>> print(f"{usage['month']}: {usage['total_requests']} requests")
65
+ """
66
+ return self._client._request("GET", "/profile/usage")
67
+
68
+ def downloads(self):
69
+ """Return the free-tier download allowance for the current window.
70
+
71
+ The unit is a simulation group — every Monte Carlo run of one
72
+ symbol/date/scenario — not a call, a run, or a file. Membership is
73
+ permanent: a group you have downloaded before is free to re-fetch
74
+ forever, in any run or file format.
75
+
76
+ Returns
77
+ -------
78
+ dict
79
+ limit : int or None
80
+ Groups per window. None on the pro and demo tiers, meaning
81
+ unlimited.
82
+ used : int
83
+ New groups added in the current window.
84
+ remaining : int or None
85
+ ``limit`` minus ``used``, floored at 0. None when unlimited.
86
+ window_hours : int
87
+ Length of the rolling window, 24.
88
+ downloaded_groups : list of str or None
89
+ Every group you have ever downloaded. None when unlimited.
90
+ downloaded_group_details : list of dict or None
91
+ The same groups, each with a ``downloaded_at`` timestamp.
92
+
93
+ Notes
94
+ -----
95
+ A request that would exceed the allowance returns HTTP 429 without
96
+ charging anything, so a partial download never silently eats quota.
97
+
98
+ Examples
99
+ --------
100
+ >>> quota = client.profile.downloads()
101
+ >>> print(f"{quota['used']}/{quota['limit']} used, {quota['remaining']} left")
102
+ """
103
+ return self._client._request("GET", "/profile/downloads")
@@ -232,6 +232,34 @@ class ValidationResource:
232
232
  exchange : str, optional
233
233
  Exchange protocol (e.g. "hkex_securities"). Defaults to
234
234
  the prefix parsed from sim_ids[0].
235
+ statistical : bool, optional
236
+ Area flag (pulse-check 1.10.0): run the statistical checks. Every
237
+ area flag left unset takes the server's default, so a job that
238
+ names none behaves exactly as it did before 1.10.0.
239
+ stylised_facts : bool, optional
240
+ Area flag: run the Cont stylised facts. Distinct from
241
+ ``run_stylised_facts``, which is the older tri-state pass toggle.
242
+ impact : bool, optional
243
+ Area flag: run the Bouchaud impact response. Distinct from
244
+ ``run_impact``, for the same reason.
245
+ volume_correlation : bool, optional
246
+ Area flag: run the volume-correlation checks.
247
+ fid : bool, optional
248
+ Area flag: compute the Frechet Inception Distance.
249
+ mind : bool, optional
250
+ Area flag: compute the Monge Inception Distance.
251
+ lob : bool, optional
252
+ Mark the supplied frames as L2 snapshots, which switches off
253
+ everything that needs the message stream.
254
+ sample_period : str, optional
255
+ The grid the book is resampled onto, e.g. "1s".
256
+ match_generated_sample : bool, optional
257
+ Resample the historical side onto the same grid as the generated
258
+ frames.
259
+ plots : bool or list of str, optional
260
+ False, True, or a list of plot ids to render.
261
+ historical_output : bool, optional
262
+ The demo-only gate that ``plot_data`` used to be.
235
263
 
236
264
  Returns
237
265
  -------
@@ -321,6 +349,52 @@ class ValidationResource:
321
349
  Notes
322
350
  -----
323
351
  The run flags mean exactly what they mean on :meth:`run`.
352
+ run_metrics : bool, optional
353
+ Compute L1/Wasserstein distributional distances. Tri-state: left
354
+ unset the API resolves it from your tier.
355
+ run_impact : bool, optional
356
+ Compute Bouchaud impact response curves. Tri-state.
357
+ run_inception_distances : bool, default True
358
+ Compute MIND and FID on DeepLOB embeddings. One flag gates both,
359
+ and unlike the others it defaults to on.
360
+ run_stylised_facts : bool, optional
361
+ Compute the eleven Cont stylised facts and their verdicts.
362
+ Tri-state.
363
+ plot_data : bool, optional
364
+ Store the raw data behind every plot. Demo tier only.
365
+ n_levels : int, default 10
366
+ L2 book levels to use. The inception distances need all 10.
367
+ l2_only : bool, default False
368
+ Restrict to metrics needing only bid/ask price and size. Disables
369
+ the impact pass.
370
+ statistical : bool, optional
371
+ Area flag (pulse-check 1.10.0): run the statistical checks. Every
372
+ area flag left unset takes the server's default, so a job that
373
+ names none behaves exactly as it did before 1.10.0.
374
+ stylised_facts : bool, optional
375
+ Area flag: run the Cont stylised facts. Distinct from
376
+ ``run_stylised_facts``, which is the older tri-state pass toggle.
377
+ impact : bool, optional
378
+ Area flag: run the Bouchaud impact response. Distinct from
379
+ ``run_impact``, for the same reason.
380
+ volume_correlation : bool, optional
381
+ Area flag: run the volume-correlation checks.
382
+ fid : bool, optional
383
+ Area flag: compute the Frechet Inception Distance.
384
+ mind : bool, optional
385
+ Area flag: compute the Monge Inception Distance.
386
+ lob : bool, optional
387
+ Mark the supplied frames as L2 snapshots, which switches off
388
+ everything that needs the message stream.
389
+ sample_period : str, optional
390
+ The grid the book is resampled onto, e.g. "1s".
391
+ match_generated_sample : bool, optional
392
+ Resample the historical side onto the same grid as the generated
393
+ frames.
394
+ plots : bool or list of str, optional
395
+ False, True, or a list of plot ids to render.
396
+ historical_output : bool, optional
397
+ The demo-only gate that ``plot_data`` used to be.
324
398
 
325
399
  Returns
326
400
  -------
@@ -496,6 +570,34 @@ class ValidationResource:
496
570
  Seconds between status checks (default 3)
497
571
  timeout : float, default 600.0
498
572
  Max seconds to wait (default 600)
573
+ statistical : bool, optional
574
+ Area flag (pulse-check 1.10.0): run the statistical checks. Every
575
+ area flag left unset takes the server's default, so a job that
576
+ names none behaves exactly as it did before 1.10.0.
577
+ stylised_facts : bool, optional
578
+ Area flag: run the Cont stylised facts. Distinct from
579
+ ``run_stylised_facts``, which is the older tri-state pass toggle.
580
+ impact : bool, optional
581
+ Area flag: run the Bouchaud impact response. Distinct from
582
+ ``run_impact``, for the same reason.
583
+ volume_correlation : bool, optional
584
+ Area flag: run the volume-correlation checks.
585
+ fid : bool, optional
586
+ Area flag: compute the Frechet Inception Distance.
587
+ mind : bool, optional
588
+ Area flag: compute the Monge Inception Distance.
589
+ lob : bool, optional
590
+ Mark the supplied frames as L2 snapshots, which switches off
591
+ everything that needs the message stream.
592
+ sample_period : str, optional
593
+ The grid the book is resampled onto, e.g. "1s".
594
+ match_generated_sample : bool, optional
595
+ Resample the historical side onto the same grid as the generated
596
+ frames.
597
+ plots : bool or list of str, optional
598
+ False, True, or a list of plot ids to render.
599
+ historical_output : bool, optional
600
+ The demo-only gate that ``plot_data`` used to be.
499
601
 
500
602
  Returns
501
603
  -------
@@ -657,18 +759,26 @@ class ValidationResource:
657
759
  }
658
760
 
659
761
  def display_plots(self, result: dict) -> "PlotDisplay":
660
- """Return a PlotDisplay object for displaying validation plots.
661
-
662
- Usage:
663
- plots = client.validation.display_plots(result)
664
- plots.distributions() # show distribution histograms
665
- plots.distances() # show spider plots
666
- plots.impact_response() # show impact response plots
762
+ """Wrap a finished validation result in a plot renderer.
667
763
 
668
764
  Parameters
669
765
  ----------
670
766
  result : dict
671
- The result dict from run_pipeline() or get_job()
767
+ The result dict from :meth:`run_pipeline` or :meth:`get_job`.
768
+
769
+ Returns
770
+ -------
771
+ PlotDisplay
772
+ Carries ``distributions()``, ``distances()``,
773
+ ``impact_response()`` and ``all()``, each of which renders in
774
+ place and returns None.
775
+
776
+ Examples
777
+ --------
778
+ >>> plots = client.validation.display_plots(result)
779
+ >>> plots.distributions() # distribution histograms
780
+ >>> plots.distances() # spider plots
781
+ >>> plots.impact_response() # impact response curves
672
782
  """
673
783
  return PlotDisplay(result)
674
784
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simudyne-pulse
3
- Version: 0.7.0.dev5
3
+ Version: 0.7.0.dev6
4
4
  Summary: Python SDK for the Simudyne Pulse synthetic market data API
5
5
  Author-email: Simudyne <support@simudyne.com>
6
6
  License-Expression: MIT
@@ -1,12 +0,0 @@
1
- class ApiKeysResource:
2
- def __init__(self, client):
3
- self._client = client
4
-
5
- def create(self, name: str):
6
- return self._client._request("POST", "/api-keys", json={"name": name})
7
-
8
- def list(self):
9
- return self._client._request("GET", "/api-keys")
10
-
11
- def revoke(self, key_id: str):
12
- return self._client._request("DELETE", f"/api-keys/{key_id}")
@@ -1,30 +0,0 @@
1
- class ProfileResource:
2
- def __init__(self, client):
3
- self._client = client
4
-
5
- def get(self):
6
- return self._client._request("GET", "/profile")
7
-
8
- def usage(self):
9
- return self._client._request("GET", "/profile/usage")
10
-
11
- def downloads(self):
12
- """Download quota usage for the current rolling 24-hour window.
13
-
14
- Returns a dict with ``limit``, ``used``, ``remaining``,
15
- ``window_hours`` and ``downloaded_groups``. ``limit`` and
16
- ``remaining`` are ``None`` on the pro and demo tiers (unlimited); on
17
- the free tier they reflect the account's daily download allowance.
18
-
19
- A "download" is one simulation group (all Monte Carlo runs of one
20
- scenario). ``used`` counts NEW groups added in the window;
21
- ``downloaded_groups`` lists every group you have ever downloaded —
22
- membership is permanent, so those are free to re-fetch forever in any
23
- run or file format.
24
-
25
- Example:
26
- >>> quota = client.profile.downloads()
27
- >>> print(f"{quota['used']}/{quota['limit']} used, {quota['remaining']} left")
28
- >>> print(f"{len(quota['downloaded_groups'])} groups owned")
29
- """
30
- return self._client._request("GET", "/profile/downloads")