simudyne-pulse 0.7.0.dev13__tar.gz → 0.7.0.dev14__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 (26) hide show
  1. {simudyne_pulse-0.7.0.dev13/src/simudyne_pulse.egg-info → simudyne_pulse-0.7.0.dev14}/PKG-INFO +1 -1
  2. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/pyproject.toml +1 -1
  3. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/src/simudyne/resources/validation.py +15 -11
  4. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14/src/simudyne_pulse.egg-info}/PKG-INFO +1 -1
  5. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/tests/test_validation.py +24 -1
  6. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/LICENSE +0 -0
  7. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/README.md +0 -0
  8. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/setup.cfg +0 -0
  9. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/src/simudyne/__init__.py +0 -0
  10. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/src/simudyne/client.py +0 -0
  11. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/src/simudyne/exceptions.py +0 -0
  12. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/src/simudyne/resources/__init__.py +0 -0
  13. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/src/simudyne/resources/api_keys.py +0 -0
  14. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/src/simudyne/resources/data.py +0 -0
  15. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/src/simudyne/resources/fix.py +0 -0
  16. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/src/simudyne/resources/fm.py +0 -0
  17. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/src/simudyne/resources/historical.py +0 -0
  18. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/src/simudyne/resources/profile.py +0 -0
  19. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/src/simudyne/resources/simulation.py +0 -0
  20. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/src/simudyne/resources/simulator_gym.py +0 -0
  21. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/src/simudyne_pulse.egg-info/SOURCES.txt +0 -0
  22. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/src/simudyne_pulse.egg-info/dependency_links.txt +0 -0
  23. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/src/simudyne_pulse.egg-info/requires.txt +0 -0
  24. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/src/simudyne_pulse.egg-info/top_level.txt +0 -0
  25. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/tests/test_new_resources.py +0 -0
  26. {simudyne_pulse-0.7.0.dev13 → simudyne_pulse-0.7.0.dev14}/tests/test_simulator_gym.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simudyne-pulse
3
- Version: 0.7.0.dev13
3
+ Version: 0.7.0.dev14
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.13"
7
+ version = "0.7.0-dev.14"
8
8
  description = "Python SDK for the Simudyne Pulse synthetic market data API"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -9,7 +9,7 @@ Submit, then poll::
9
9
 
10
10
  job = client.validation.run(
11
11
  symbol="BARC", date="2026-06-17", provider="bmll", exchange="lse",
12
- sim_ids=[...], ticksize=0.05,
12
+ sim_ids=[...],
13
13
  )
14
14
  result = client.validation.get_job(job["job_id"])
15
15
  result["distances"]["spread"]["l1"] # per simulation
@@ -27,6 +27,14 @@ default for your tier, resolved server-side, so naming none behaves exactly as
27
27
  your account is entitled to. Pass ``False`` to skip an expensive pass or
28
28
  ``True`` to force one on.
29
29
 
30
+ Tick size
31
+ ---------
32
+ Read off the historical day — the metadata sidecar, else pulse_format's own
33
+ metadata for that day's ``full_data.parquet``. It is not a parameter. The
34
+ result reports ``metadata["ticksize"]`` and ``metadata["ticksize_source"]``;
35
+ a source of ``"fallback"`` means none was found and 1.0 was assumed, which
36
+ puts the impact response in price units rather than ticks.
37
+
30
38
  The historical gate
31
39
  -------------------
32
40
  Whether the historical half of the comparison comes back — the series in the
@@ -186,7 +194,6 @@ class ValidationResource:
186
194
  *,
187
195
  sim_ids=None,
188
196
  sim_files=None,
189
- ticksize: float = 1.0,
190
197
  statistical=None,
191
198
  stylised_facts=None,
192
199
  impact=None,
@@ -217,7 +224,10 @@ class ValidationResource:
217
224
  exists under both with different dates and tick sizes, so
218
225
  ``(symbol, provider, exchange)`` is the identity, not the symbol.
219
226
  exchange : str
220
- Exchange, e.g. ``"lse"`` or ``"hkex_securities"``.
227
+ Exchange, e.g. ``"lse"`` or ``"hkex_securities"``. The tick size
228
+ is read off the historical day for this instrument rather than
229
+ passed in; ``metadata["ticksize"]`` reports the value used and
230
+ ``metadata["ticksize_source"]`` where it came from.
221
231
  sim_ids : list of str or dict, optional
222
232
  Platform simulation IDs, 1 to 25. A flat list is one unnamed
223
233
  population. A mapping — ``{"fm": [...], "abm": [...]}`` — compares
@@ -229,8 +239,6 @@ class ValidationResource:
229
239
  Your own simulated runs, up to 25: paths, ``(filename, bytes)``
230
240
  pairs, or polars / pandas DataFrames in pulse format. Grouped the
231
241
  same way as ``sim_ids``. The historical side is fetched for you.
232
- ticksize : float, default 1.0
233
- Minimum price increment. Should match the instrument.
234
242
  statistical, stylised_facts, impact, volume_correlation, fid, mind : bool, optional
235
243
  Whether to run each area. ``None`` uses your tier's default.
236
244
  lob : bool, optional
@@ -276,8 +284,8 @@ class ValidationResource:
276
284
  ------
277
285
  ValueError
278
286
  If neither or both of ``sim_ids`` and ``sim_files`` are given,
279
- either is empty, more than 25 runs are passed, ``ticksize`` is not
280
- positive, or ``n_levels`` is below 1. Also raised if the API
287
+ either is empty, more than 25 runs are passed, or ``n_levels``
288
+ is below 1. Also raised if the API
281
289
  accepts the request but returns no ``job_id``.
282
290
  PulseAPIError
283
291
  If the instrument has no historical data for ``date``, a
@@ -358,8 +366,6 @@ class ValidationResource:
358
366
  )
359
367
  if count > MAX_SIM_FILES:
360
368
  raise ValueError(f"Maximum {MAX_SIM_FILES} simulations per validation job")
361
- if ticksize <= 0:
362
- raise ValueError("ticksize must be positive")
363
369
  if n_levels < 1:
364
370
  raise ValueError("n_levels must be at least 1")
365
371
 
@@ -391,7 +397,6 @@ class ValidationResource:
391
397
  if isinstance(sim_ids, dict)
392
398
  else list(sim_ids)
393
399
  ),
394
- "ticksize": ticksize,
395
400
  "config": config,
396
401
  },
397
402
  )
@@ -425,7 +430,6 @@ class ValidationResource:
425
430
  "date": date,
426
431
  "provider": provider,
427
432
  "exchange": exchange,
428
- "ticksize": str(ticksize),
429
433
  "config": json.dumps(config),
430
434
  },
431
435
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simudyne-pulse
3
- Version: 0.7.0.dev13
3
+ Version: 0.7.0.dev14
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
@@ -83,7 +83,6 @@ class TestWhatToValidate:
83
83
  ({"sim_ids": SIM_IDS, "sim_files": [("a", b"x")]}, "exactly one"),
84
84
  ({"sim_ids": []}, "must not be empty"),
85
85
  ({"sim_ids": SIM_IDS * (MAX_SIM_FILES + 1)}, "Maximum 25"),
86
- ({"sim_ids": SIM_IDS, "ticksize": 0}, "ticksize must be positive"),
87
86
  ({"sim_ids": SIM_IDS, "n_levels": 0}, "at least 1"),
88
87
  ],
89
88
  )
@@ -330,3 +329,27 @@ class TestGroupShape:
330
329
  def test_the_count_still_catches_too_many(self):
331
330
  with pytest.raises(ValueError, match="Maximum 25"):
332
331
  self._submit(sim_ids={"a": ["x"] * 13, "b": ["y"] * 13})
332
+
333
+
334
+ class TestTickSizeIsNotAsked:
335
+ """It is read off the historical day, so passing one is a mistake.
336
+
337
+ The value a caller passed never reached a computation — the impact
338
+ response has always used the one pulse-check looks up — so accepting it
339
+ only let a result disagree with itself.
340
+ """
341
+
342
+ def test_run_does_not_take_it(self):
343
+ with pytest.raises(TypeError, match="ticksize"):
344
+ ValidationResource(FakeClient([{"job_id": "v1"}])).run(
345
+ sim_ids=SIM_IDS, ticksize=0.1, **IDENTITY
346
+ )
347
+
348
+ def test_it_is_not_sent(self):
349
+ client, _ = _run([{"job_id": "v1"}])
350
+ assert "ticksize" not in client.calls[0][2]["json"]
351
+
352
+ def test_an_upload_does_not_send_it_either(self):
353
+ client = FakeClient([{"job_id": "v1"}])
354
+ ValidationResource(client).run(sim_files=[("a.parquet", b"x")], **IDENTITY)
355
+ assert "ticksize" not in client.calls[0][2]["data"]