arvo-client 0.1.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.
Files changed (56) hide show
  1. arvo_client-0.1.0/.gitignore +12 -0
  2. arvo_client-0.1.0/PKG-INFO +115 -0
  3. arvo_client-0.1.0/README.md +96 -0
  4. arvo_client-0.1.0/pyproject.toml +37 -0
  5. arvo_client-0.1.0/src/arvo/__init__.py +468 -0
  6. arvo_client-0.1.0/src/arvo/common/__init__.py +0 -0
  7. arvo_client-0.1.0/src/arvo/common/v1/__init__.py +0 -0
  8. arvo_client-0.1.0/src/arvo/common/v1/models_pb2.py +38 -0
  9. arvo_client-0.1.0/src/arvo/common/v1/models_pb2_grpc.py +24 -0
  10. arvo_client-0.1.0/src/arvo/market/__init__.py +0 -0
  11. arvo_client-0.1.0/src/arvo/market/v1/__init__.py +0 -0
  12. arvo_client-0.1.0/src/arvo/market/v1/models_pb2.py +46 -0
  13. arvo_client-0.1.0/src/arvo/market/v1/models_pb2_grpc.py +24 -0
  14. arvo_client-0.1.0/src/arvo/market/v1/views_pb2.py +56 -0
  15. arvo_client-0.1.0/src/arvo/market/v1/views_pb2_grpc.py +24 -0
  16. arvo_client-0.1.0/src/arvo/platform/__init__.py +0 -0
  17. arvo_client-0.1.0/src/arvo/platform/v1/__init__.py +0 -0
  18. arvo_client-0.1.0/src/arvo/platform/v1/models_pb2.py +50 -0
  19. arvo_client-0.1.0/src/arvo/platform/v1/models_pb2_grpc.py +24 -0
  20. arvo_client-0.1.0/src/arvo/platform/v1/views_pb2.py +90 -0
  21. arvo_client-0.1.0/src/arvo/platform/v1/views_pb2_grpc.py +24 -0
  22. arvo_client-0.1.0/src/arvo/portfolio/__init__.py +0 -0
  23. arvo_client-0.1.0/src/arvo/portfolio/v1/__init__.py +0 -0
  24. arvo_client-0.1.0/src/arvo/portfolio/v1/models_pb2.py +36 -0
  25. arvo_client-0.1.0/src/arvo/portfolio/v1/models_pb2_grpc.py +24 -0
  26. arvo_client-0.1.0/src/arvo/portfolio/v1/views_pb2.py +48 -0
  27. arvo_client-0.1.0/src/arvo/portfolio/v1/views_pb2_grpc.py +24 -0
  28. arvo_client-0.1.0/src/arvo/py.typed +0 -0
  29. arvo_client-0.1.0/src/arvo/research/__init__.py +0 -0
  30. arvo_client-0.1.0/src/arvo/research/v1/__init__.py +0 -0
  31. arvo_client-0.1.0/src/arvo/research/v1/models_pb2.py +100 -0
  32. arvo_client-0.1.0/src/arvo/research/v1/models_pb2_grpc.py +24 -0
  33. arvo_client-0.1.0/src/arvo/research/v1/views_pb2.py +110 -0
  34. arvo_client-0.1.0/src/arvo/research/v1/views_pb2_grpc.py +24 -0
  35. arvo_client-0.1.0/src/arvo/services/__init__.py +0 -0
  36. arvo_client-0.1.0/src/arvo/services/v1/__init__.py +0 -0
  37. arvo_client-0.1.0/src/arvo/services/v1/accounts_pb2.py +39 -0
  38. arvo_client-0.1.0/src/arvo/services/v1/accounts_pb2_grpc.py +246 -0
  39. arvo_client-0.1.0/src/arvo/services/v1/market_pb2.py +39 -0
  40. arvo_client-0.1.0/src/arvo/services/v1/market_pb2_grpc.py +375 -0
  41. arvo_client-0.1.0/src/arvo/services/v1/platform_pb2.py +39 -0
  42. arvo_client-0.1.0/src/arvo/services/v1/platform_pb2_grpc.py +377 -0
  43. arvo_client-0.1.0/src/arvo/services/v1/portfolio_pb2.py +39 -0
  44. arvo_client-0.1.0/src/arvo/services/v1/portfolio_pb2_grpc.py +202 -0
  45. arvo_client-0.1.0/src/arvo/services/v1/research_pb2.py +43 -0
  46. arvo_client-0.1.0/src/arvo/services/v1/research_pb2_grpc.py +1372 -0
  47. arvo_client-0.1.0/src/arvo/services/v1/scripts_pb2.py +39 -0
  48. arvo_client-0.1.0/src/arvo/services/v1/scripts_pb2_grpc.py +357 -0
  49. arvo_client-0.1.0/src/arvo/services/v1/sessions_pb2.py +38 -0
  50. arvo_client-0.1.0/src/arvo/services/v1/sessions_pb2_grpc.py +369 -0
  51. arvo_client-0.1.0/src/arvo/session/__init__.py +0 -0
  52. arvo_client-0.1.0/src/arvo/session/v1/__init__.py +0 -0
  53. arvo_client-0.1.0/src/arvo/session/v1/models_pb2.py +44 -0
  54. arvo_client-0.1.0/src/arvo/session/v1/models_pb2_grpc.py +24 -0
  55. arvo_client-0.1.0/tests/test_client.py +224 -0
  56. arvo_client-0.1.0/uv.lock +740 -0
@@ -0,0 +1,12 @@
1
+ # Rust
2
+ rust/target/
3
+
4
+ # Python
5
+ python/.venv/
6
+ python/dist/
7
+ __pycache__/
8
+ *.pyc
9
+ .pytest_cache/
10
+
11
+ # A file Windows makes when a command is redirected to NUL from the wrong shell.
12
+ nul
@@ -0,0 +1,115 @@
1
+ Metadata-Version: 2.5
2
+ Name: arvo-client
3
+ Version: 0.1.0
4
+ Summary: Arvo's engine from Python: a research client that reads findings and runs studies, and the generated stubs for every service.
5
+ Project-URL: Homepage, https://github.com/wjpin84/arvo-engine-api
6
+ Project-URL: Documentation, https://github.com/wjpin84/arvo-engine-api/blob/main/python/README.md
7
+ Project-URL: Changelog, https://github.com/wjpin84/arvo-engine-api/blob/main/CHANGELOG.md
8
+ License-Expression: Apache-2.0
9
+ Keywords: arvo,grpc,research,trading
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Office/Business :: Financial :: Investment
13
+ Classifier: Typing :: Typed
14
+ Requires-Python: >=3.10
15
+ Requires-Dist: grpcio>=1.75.1
16
+ Requires-Dist: pandas>=2
17
+ Requires-Dist: protobuf>=6.31.1
18
+ Description-Content-Type: text/markdown
19
+
20
+ # arvo (Python)
21
+
22
+ Arvo's research from Python: read research memory, run studies and
23
+ walk-forwards, and load the bar library into pandas. It talks to a running
24
+ `arvo-engine` through the research API of the
25
+ [contract](https://github.com/wjpin84/arvo-engine-api), which has no call
26
+ that fetches, touches a credential or trades.
27
+
28
+ ```sh
29
+ pip install arvo-client # the package is `arvo-client`; the module is `arvo`
30
+ ```
31
+
32
+ ```python
33
+ import arvo
34
+
35
+ engine = arvo.connect() # reads engine.json from the Arvo app data directory
36
+ found = engine.run_study("AAPL.RH", "sma_cross", author="script:first-look")
37
+ print(found.verdict) # read these three before any number
38
+ print(found.read_this_first)
39
+ for item in found.advice:
40
+ print(item.severity, item.finding, "->", item.action)
41
+ print(found.detail["out_of_sample"])
42
+
43
+ prices = engine.bars("AAPL.RH") # pandas DataFrame, read-only
44
+ ```
45
+
46
+ **`author` is required, and it matters.** A run is saved as that author's
47
+ finding and deflated against everything the author has run, so a script
48
+ trying configurations until one passes does not make it pass.
49
+
50
+ ## What is in the package
51
+
52
+ Two layers, and you can use either.
53
+
54
+ **`arvo`**, the client: `connect()`, `Engine`, and plain dataclasses for what
55
+ comes back (`Finding`, `Advice`, `Strategy`, ...). This is what a script
56
+ wants. It reads only `engine.json`, so it holds only the research token: it
57
+ cannot reach the control tier that fetches data, holds credentials or trades,
58
+ and that is by construction rather than by policy.
59
+
60
+ **`arvo.<domain>.v1`**, the generated stubs: one module per proto package
61
+ (`arvo.research.v1.models_pb2`, `arvo.research.v1.views_pb2`, and so on) and
62
+ the services under `arvo.services.v1`. Use these for anything the client
63
+ does not wrap, or to reach the control tier from a front end you are writing
64
+ yourself, with the token from `control.json`:
65
+
66
+ ```python
67
+ import grpc, json, pathlib
68
+ from arvo.services.v1 import platform_pb2_grpc
69
+ from arvo.common.v1 import models_pb2 as common
70
+
71
+ root = arvo.default_root()
72
+ address = json.loads((root / "engine.json").read_text())["address"]
73
+ control = json.loads((root / "control.json").read_text())["token"]
74
+ platform = platform_pb2_grpc.PlatformStub(grpc.insecure_channel(address))
75
+ metadata = (("authorization", f"Bearer {control}"),)
76
+ for job in platform.ListJobs(common.Empty(), metadata=metadata).jobs:
77
+ print(job.id, job.label, job.next_run_at)
78
+ ```
79
+
80
+ Every message and field carries the comment written on it in the protos;
81
+ `help(models_pb2.StudyView)` shows what your editor does.
82
+
83
+ ## Setup for development
84
+
85
+ ```sh
86
+ cd python && uv sync
87
+ ```
88
+
89
+ The tests start a real `arvo-engine` over a temporary directory, so they
90
+ need one built. Point them at it:
91
+
92
+ ```sh
93
+ ARVO_ENGINE=/path/to/arvo-engine uv run pytest
94
+ ```
95
+
96
+ Without it they are skipped, not failed.
97
+
98
+ ## Regenerating the stubs
99
+
100
+ The modules under `src/arvo/*/v1` are generated from `../protos` and
101
+ committed. After a proto changes:
102
+
103
+ ```sh
104
+ cd python && uv run python -m grpc_tools.protoc -I ../protos --python_out=src --grpc_python_out=src $(find ../protos -name '*.proto')
105
+ ```
106
+
107
+ ## Versioning
108
+
109
+ This package, `arvo-api` and `arvo-client` on crates.io share one version
110
+ with the protos they are generated from. The rules are in
111
+ [VERSIONING.md](https://github.com/wjpin84/arvo-engine-api/blob/main/VERSIONING.md).
112
+
113
+ ## License
114
+
115
+ Apache-2.0.
@@ -0,0 +1,96 @@
1
+ # arvo (Python)
2
+
3
+ Arvo's research from Python: read research memory, run studies and
4
+ walk-forwards, and load the bar library into pandas. It talks to a running
5
+ `arvo-engine` through the research API of the
6
+ [contract](https://github.com/wjpin84/arvo-engine-api), which has no call
7
+ that fetches, touches a credential or trades.
8
+
9
+ ```sh
10
+ pip install arvo-client # the package is `arvo-client`; the module is `arvo`
11
+ ```
12
+
13
+ ```python
14
+ import arvo
15
+
16
+ engine = arvo.connect() # reads engine.json from the Arvo app data directory
17
+ found = engine.run_study("AAPL.RH", "sma_cross", author="script:first-look")
18
+ print(found.verdict) # read these three before any number
19
+ print(found.read_this_first)
20
+ for item in found.advice:
21
+ print(item.severity, item.finding, "->", item.action)
22
+ print(found.detail["out_of_sample"])
23
+
24
+ prices = engine.bars("AAPL.RH") # pandas DataFrame, read-only
25
+ ```
26
+
27
+ **`author` is required, and it matters.** A run is saved as that author's
28
+ finding and deflated against everything the author has run, so a script
29
+ trying configurations until one passes does not make it pass.
30
+
31
+ ## What is in the package
32
+
33
+ Two layers, and you can use either.
34
+
35
+ **`arvo`**, the client: `connect()`, `Engine`, and plain dataclasses for what
36
+ comes back (`Finding`, `Advice`, `Strategy`, ...). This is what a script
37
+ wants. It reads only `engine.json`, so it holds only the research token: it
38
+ cannot reach the control tier that fetches data, holds credentials or trades,
39
+ and that is by construction rather than by policy.
40
+
41
+ **`arvo.<domain>.v1`**, the generated stubs: one module per proto package
42
+ (`arvo.research.v1.models_pb2`, `arvo.research.v1.views_pb2`, and so on) and
43
+ the services under `arvo.services.v1`. Use these for anything the client
44
+ does not wrap, or to reach the control tier from a front end you are writing
45
+ yourself, with the token from `control.json`:
46
+
47
+ ```python
48
+ import grpc, json, pathlib
49
+ from arvo.services.v1 import platform_pb2_grpc
50
+ from arvo.common.v1 import models_pb2 as common
51
+
52
+ root = arvo.default_root()
53
+ address = json.loads((root / "engine.json").read_text())["address"]
54
+ control = json.loads((root / "control.json").read_text())["token"]
55
+ platform = platform_pb2_grpc.PlatformStub(grpc.insecure_channel(address))
56
+ metadata = (("authorization", f"Bearer {control}"),)
57
+ for job in platform.ListJobs(common.Empty(), metadata=metadata).jobs:
58
+ print(job.id, job.label, job.next_run_at)
59
+ ```
60
+
61
+ Every message and field carries the comment written on it in the protos;
62
+ `help(models_pb2.StudyView)` shows what your editor does.
63
+
64
+ ## Setup for development
65
+
66
+ ```sh
67
+ cd python && uv sync
68
+ ```
69
+
70
+ The tests start a real `arvo-engine` over a temporary directory, so they
71
+ need one built. Point them at it:
72
+
73
+ ```sh
74
+ ARVO_ENGINE=/path/to/arvo-engine uv run pytest
75
+ ```
76
+
77
+ Without it they are skipped, not failed.
78
+
79
+ ## Regenerating the stubs
80
+
81
+ The modules under `src/arvo/*/v1` are generated from `../protos` and
82
+ committed. After a proto changes:
83
+
84
+ ```sh
85
+ cd python && uv run python -m grpc_tools.protoc -I ../protos --python_out=src --grpc_python_out=src $(find ../protos -name '*.proto')
86
+ ```
87
+
88
+ ## Versioning
89
+
90
+ This package, `arvo-api` and `arvo-client` on crates.io share one version
91
+ with the protos they are generated from. The rules are in
92
+ [VERSIONING.md](https://github.com/wjpin84/arvo-engine-api/blob/main/VERSIONING.md).
93
+
94
+ ## License
95
+
96
+ Apache-2.0.
@@ -0,0 +1,37 @@
1
+ [project]
2
+ # `arvo` on PyPI belongs to someone else; the module is still `arvo`.
3
+ name = "arvo-client"
4
+ version = "0.1.0"
5
+ description = "Arvo's engine from Python: a research client that reads findings and runs studies, and the generated stubs for every service."
6
+ readme = "README.md"
7
+ license = "Apache-2.0"
8
+ keywords = ["arvo", "trading", "research", "grpc"]
9
+ classifiers = [
10
+ "Programming Language :: Python :: 3",
11
+ "License :: OSI Approved :: Apache Software License",
12
+ "Topic :: Office/Business :: Financial :: Investment",
13
+ "Typing :: Typed",
14
+ ]
15
+ requires-python = ">=3.10"
16
+ dependencies = [
17
+ # The stubs under src/arvo/*/v1 were generated with grpcio-tools 1.75.1,
18
+ # which require at least these runtimes.
19
+ "grpcio>=1.75.1",
20
+ "protobuf>=6.31.1",
21
+ "pandas>=2",
22
+ ]
23
+
24
+ [project.urls]
25
+ Homepage = "https://github.com/wjpin84/arvo-engine-api"
26
+ Documentation = "https://github.com/wjpin84/arvo-engine-api/blob/main/python/README.md"
27
+ Changelog = "https://github.com/wjpin84/arvo-engine-api/blob/main/CHANGELOG.md"
28
+
29
+ [dependency-groups]
30
+ dev = ["pytest>=8", "grpcio-tools==1.75.1"]
31
+
32
+ [build-system]
33
+ requires = ["hatchling"]
34
+ build-backend = "hatchling.build"
35
+
36
+ [tool.hatch.build.targets.wheel]
37
+ packages = ["src/arvo"]