mangroveai 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.
- mangroveai-0.1.0/.github/workflows/release.yml +118 -0
- mangroveai-0.1.0/.gitignore +10 -0
- mangroveai-0.1.0/CHANGELOG.md +45 -0
- mangroveai-0.1.0/LICENSE +21 -0
- mangroveai-0.1.0/PKG-INFO +189 -0
- mangroveai-0.1.0/README.md +158 -0
- mangroveai-0.1.0/examples/quickstart.py +119 -0
- mangroveai-0.1.0/pyproject.toml +67 -0
- mangroveai-0.1.0/src/mangroveai/__init__.py +44 -0
- mangroveai-0.1.0/src/mangroveai/_client.py +158 -0
- mangroveai-0.1.0/src/mangroveai/_config.py +60 -0
- mangroveai-0.1.0/src/mangroveai/_constants.py +39 -0
- mangroveai-0.1.0/src/mangroveai/_pagination.py +35 -0
- mangroveai-0.1.0/src/mangroveai/_services/__init__.py +0 -0
- mangroveai-0.1.0/src/mangroveai/_services/_base.py +57 -0
- mangroveai-0.1.0/src/mangroveai/_services/auth.py +73 -0
- mangroveai-0.1.0/src/mangroveai/_services/backtesting.py +121 -0
- mangroveai-0.1.0/src/mangroveai/_services/crypto_assets.py +103 -0
- mangroveai-0.1.0/src/mangroveai/_services/defi.py +28 -0
- mangroveai-0.1.0/src/mangroveai/_services/docs.py +20 -0
- mangroveai-0.1.0/src/mangroveai/_services/execution.py +126 -0
- mangroveai-0.1.0/src/mangroveai/_services/kb/__init__.py +53 -0
- mangroveai-0.1.0/src/mangroveai/_services/kb/compute.py +46 -0
- mangroveai-0.1.0/src/mangroveai/_services/kb/documents.py +21 -0
- mangroveai-0.1.0/src/mangroveai/_services/kb/glossary.py +20 -0
- mangroveai-0.1.0/src/mangroveai/_services/kb/indicators.py +24 -0
- mangroveai-0.1.0/src/mangroveai/_services/kb/search.py +31 -0
- mangroveai-0.1.0/src/mangroveai/_services/kb/signals.py +27 -0
- mangroveai-0.1.0/src/mangroveai/_services/kb/tags.py +17 -0
- mangroveai-0.1.0/src/mangroveai/_services/on_chain.py +91 -0
- mangroveai-0.1.0/src/mangroveai/_services/signals.py +121 -0
- mangroveai-0.1.0/src/mangroveai/_services/social.py +39 -0
- mangroveai-0.1.0/src/mangroveai/_services/strategies.py +92 -0
- mangroveai-0.1.0/src/mangroveai/_transport/__init__.py +20 -0
- mangroveai-0.1.0/src/mangroveai/_transport/_auth.py +50 -0
- mangroveai-0.1.0/src/mangroveai/_transport/_http.py +131 -0
- mangroveai-0.1.0/src/mangroveai/_transport/_mock.py +86 -0
- mangroveai-0.1.0/src/mangroveai/_transport/_protocol.py +37 -0
- mangroveai-0.1.0/src/mangroveai/_transport/_retry.py +32 -0
- mangroveai-0.1.0/src/mangroveai/_transport/_service.py +53 -0
- mangroveai-0.1.0/src/mangroveai/_version.py +1 -0
- mangroveai-0.1.0/src/mangroveai/exceptions.py +100 -0
- mangroveai-0.1.0/src/mangroveai/models/__init__.py +140 -0
- mangroveai-0.1.0/src/mangroveai/models/_base.py +11 -0
- mangroveai-0.1.0/src/mangroveai/models/auth.py +54 -0
- mangroveai-0.1.0/src/mangroveai/models/backtesting.py +125 -0
- mangroveai-0.1.0/src/mangroveai/models/crypto_assets.py +94 -0
- mangroveai-0.1.0/src/mangroveai/models/defi.py +34 -0
- mangroveai-0.1.0/src/mangroveai/models/docs.py +20 -0
- mangroveai-0.1.0/src/mangroveai/models/execution.py +100 -0
- mangroveai-0.1.0/src/mangroveai/models/kb.py +146 -0
- mangroveai-0.1.0/src/mangroveai/models/on_chain.py +68 -0
- mangroveai-0.1.0/src/mangroveai/models/shared.py +10 -0
- mangroveai-0.1.0/src/mangroveai/models/signals.py +71 -0
- mangroveai-0.1.0/src/mangroveai/models/social.py +35 -0
- mangroveai-0.1.0/src/mangroveai/models/strategies.py +61 -0
- mangroveai-0.1.0/src/mangroveai/py.typed +0 -0
- mangroveai-0.1.0/tests/__init__.py +0 -0
- mangroveai-0.1.0/tests/conftest.py +22 -0
- mangroveai-0.1.0/tests/integration/__init__.py +0 -0
- mangroveai-0.1.0/tests/integration/test_live.py +418 -0
- mangroveai-0.1.0/tests/test_auth.py +135 -0
- mangroveai-0.1.0/tests/test_backtesting.py +226 -0
- mangroveai-0.1.0/tests/test_crypto_assets.py +230 -0
- mangroveai-0.1.0/tests/test_docs.py +60 -0
- mangroveai-0.1.0/tests/test_execution.py +218 -0
- mangroveai-0.1.0/tests/test_kb/__init__.py +0 -0
- mangroveai-0.1.0/tests/test_kb/test_kb.py +320 -0
- mangroveai-0.1.0/tests/test_signals.py +192 -0
- mangroveai-0.1.0/tests/test_strategies.py +180 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
name: Release to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
bump:
|
|
7
|
+
description: "Version bump type"
|
|
8
|
+
required: true
|
|
9
|
+
type: choice
|
|
10
|
+
options:
|
|
11
|
+
- patch
|
|
12
|
+
- minor
|
|
13
|
+
- major
|
|
14
|
+
default: patch
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: write
|
|
18
|
+
id-token: write
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
release:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- name: Checkout
|
|
25
|
+
uses: actions/checkout@v4
|
|
26
|
+
with:
|
|
27
|
+
fetch-depth: 0
|
|
28
|
+
fetch-tags: true
|
|
29
|
+
|
|
30
|
+
- name: Set up Python
|
|
31
|
+
uses: actions/setup-python@v5
|
|
32
|
+
with:
|
|
33
|
+
python-version: "3.12"
|
|
34
|
+
|
|
35
|
+
- name: Install dependencies
|
|
36
|
+
run: pip install -e ".[dev]"
|
|
37
|
+
|
|
38
|
+
- name: Run tests
|
|
39
|
+
run: pytest tests/ --ignore=tests/integration -v
|
|
40
|
+
|
|
41
|
+
- name: Compute next version
|
|
42
|
+
id: version
|
|
43
|
+
env:
|
|
44
|
+
BUMP_TYPE: ${{ github.event.inputs.bump }}
|
|
45
|
+
run: |
|
|
46
|
+
LATEST_TAG=$(git tag -l 'v*' --sort=-v:refname | head -1)
|
|
47
|
+
if [ -z "$LATEST_TAG" ]; then
|
|
48
|
+
LATEST_TAG="v0.0.0"
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
CURRENT="${LATEST_TAG#v}"
|
|
52
|
+
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT"
|
|
53
|
+
|
|
54
|
+
case "$BUMP_TYPE" in
|
|
55
|
+
major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;;
|
|
56
|
+
minor) MINOR=$((MINOR + 1)); PATCH=0 ;;
|
|
57
|
+
patch) PATCH=$((PATCH + 1)) ;;
|
|
58
|
+
esac
|
|
59
|
+
|
|
60
|
+
NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}"
|
|
61
|
+
echo "version=${NEW_VERSION}" >> "$GITHUB_OUTPUT"
|
|
62
|
+
echo "tag=v${NEW_VERSION}" >> "$GITHUB_OUTPUT"
|
|
63
|
+
echo "previous=${LATEST_TAG}" >> "$GITHUB_OUTPUT"
|
|
64
|
+
echo "Releasing: ${LATEST_TAG} -> v${NEW_VERSION}"
|
|
65
|
+
|
|
66
|
+
- name: Update version in pyproject.toml
|
|
67
|
+
env:
|
|
68
|
+
NEW_VERSION: ${{ steps.version.outputs.version }}
|
|
69
|
+
run: |
|
|
70
|
+
sed -i "s/^version = .*/version = \"${NEW_VERSION}\"/" pyproject.toml
|
|
71
|
+
sed -i "s/^__version__ = .*/__version__ = \"${NEW_VERSION}\"/" src/mangroveai/_version.py
|
|
72
|
+
|
|
73
|
+
- name: Create and push tag
|
|
74
|
+
env:
|
|
75
|
+
VERSION_TAG: ${{ steps.version.outputs.tag }}
|
|
76
|
+
NEW_VERSION: ${{ steps.version.outputs.version }}
|
|
77
|
+
run: |
|
|
78
|
+
git config user.name "github-actions[bot]"
|
|
79
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
80
|
+
git add pyproject.toml src/mangroveai/_version.py
|
|
81
|
+
git diff --cached --quiet || git commit -m "release: v${NEW_VERSION}"
|
|
82
|
+
git tag -a "$VERSION_TAG" -m "Release $VERSION_TAG"
|
|
83
|
+
git push origin HEAD:main --follow-tags
|
|
84
|
+
|
|
85
|
+
- name: Build package
|
|
86
|
+
run: |
|
|
87
|
+
pip install build
|
|
88
|
+
python -m build
|
|
89
|
+
|
|
90
|
+
- name: Verify built version
|
|
91
|
+
env:
|
|
92
|
+
EXPECTED_VERSION: ${{ steps.version.outputs.version }}
|
|
93
|
+
run: |
|
|
94
|
+
echo "Expected: ${EXPECTED_VERSION}"
|
|
95
|
+
BUILT=$(unzip -p dist/*.whl '*/METADATA' | grep '^Version:' | cut -d' ' -f2)
|
|
96
|
+
echo "Built: ${BUILT}"
|
|
97
|
+
if [ "$BUILT" != "$EXPECTED_VERSION" ]; then
|
|
98
|
+
echo "ERROR: Version mismatch!"
|
|
99
|
+
exit 1
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
- name: Publish to PyPI
|
|
103
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
104
|
+
with:
|
|
105
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
106
|
+
|
|
107
|
+
- name: Create GitHub Release
|
|
108
|
+
uses: softprops/action-gh-release@v2
|
|
109
|
+
with:
|
|
110
|
+
tag_name: ${{ steps.version.outputs.tag }}
|
|
111
|
+
name: ${{ steps.version.outputs.tag }}
|
|
112
|
+
generate_release_notes: true
|
|
113
|
+
body: |
|
|
114
|
+
## mangroveai ${{ steps.version.outputs.version }}
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
pip install mangroveai==${{ steps.version.outputs.version }}
|
|
118
|
+
```
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to the MangroveAI Python SDK will be documented in this file.
|
|
4
|
+
|
|
5
|
+
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
|
+
This project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-04-12
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
**Layer 1 -- MangroveAI Core API (45 methods)**
|
|
13
|
+
- `client.auth` -- login, refresh, API key management (5 methods)
|
|
14
|
+
- `client.strategies` -- CRUD, status updates, execution state (8 methods)
|
|
15
|
+
- `client.backtesting` -- sync, async, bulk backtesting with polling (7 methods)
|
|
16
|
+
- `client.signals` -- discovery, search, match, evaluate, validate (7 methods)
|
|
17
|
+
- `client.crypto_assets` -- assets, exchanges, OHLCV, market data, trending (8 methods)
|
|
18
|
+
- `client.execution` -- accounts, positions, trades, strategy evaluation (8 methods)
|
|
19
|
+
- `client.docs` -- documentation listing and content (2 methods)
|
|
20
|
+
|
|
21
|
+
**Layer 2 -- Knowledge Base API (15 methods)**
|
|
22
|
+
- `client.kb.documents` -- document listing, content, sections (3 methods)
|
|
23
|
+
- `client.kb.search` -- full-text search with BM25 ranking (1 method)
|
|
24
|
+
- `client.kb.tags` -- tag listing and filtering (2 methods)
|
|
25
|
+
- `client.kb.glossary` -- glossary terms and backlinks (3 methods)
|
|
26
|
+
- `client.kb.signals` -- signal metadata from KB (2 methods)
|
|
27
|
+
- `client.kb.indicators` -- indicator metadata from KB (2 methods)
|
|
28
|
+
- `client.kb.compute` -- x402 paid signal/indicator computation (2 methods)
|
|
29
|
+
|
|
30
|
+
**Layer 3 -- Stubs (12 methods)**
|
|
31
|
+
- `client.on_chain` -- smart money, whale activity, exchange flows (6 methods, raises NotImplementedLayerError)
|
|
32
|
+
- `client.defi` -- protocol TVL, chain TVL, stablecoin metrics (3 methods, raises NotImplementedLayerError)
|
|
33
|
+
- `client.social` -- sentiment, mentions, influence scoring (3 methods, raises NotImplementedLayerError)
|
|
34
|
+
|
|
35
|
+
**Infrastructure**
|
|
36
|
+
- Transport layer with httpx, retry logic, and exponential backoff
|
|
37
|
+
- Auth strategies: API key, JWT with auto-refresh, x402 wallet, NoAuth
|
|
38
|
+
- Environment auto-detection from API key prefix (dev/prod)
|
|
39
|
+
- Multi-service routing (MangroveAI API + KB API with separate base URLs)
|
|
40
|
+
- PaginatedResponse with auto-pagination iterators
|
|
41
|
+
- Custom exception hierarchy matching server error format
|
|
42
|
+
- MockTransport for unit testing
|
|
43
|
+
- 41 Pydantic v2 response/request models with forward compatibility (extra="allow")
|
|
44
|
+
- 72 unit tests, 24 integration tests against live API
|
|
45
|
+
- Quickstart example verified against production
|
mangroveai-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mangrove Technologies Inc.
|
|
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.
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mangroveai
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for the MangroveAI trading strategy platform
|
|
5
|
+
Project-URL: Homepage, https://mangrovedeveloper.ai
|
|
6
|
+
Project-URL: Repository, https://github.com/MangroveTechnologies/MangroveAI-SDK
|
|
7
|
+
Project-URL: Documentation, https://github.com/MangroveTechnologies/MangroveAI-SDK#readme
|
|
8
|
+
Project-URL: Changelog, https://github.com/MangroveTechnologies/MangroveAI-SDK/blob/main/CHANGELOG.md
|
|
9
|
+
Author: Mangrove Technologies Inc.
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: httpx<1.0,>=0.27.0
|
|
22
|
+
Requires-Dist: pydantic<3.0,>=2.0
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: respx>=0.22; extra == 'dev'
|
|
29
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# MangroveAI Python SDK
|
|
33
|
+
|
|
34
|
+
Python SDK for the [MangroveAI](https://mangrovedeveloper.ai) trading strategy platform.
|
|
35
|
+
|
|
36
|
+
## Install
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install mangroveai
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Setup
|
|
43
|
+
|
|
44
|
+
1. Create an account at [mangrovedeveloper.ai](https://mangrovedeveloper.ai)
|
|
45
|
+
2. Navigate to **Settings > API Keys**
|
|
46
|
+
3. Generate a new API key
|
|
47
|
+
4. Set it as an environment variable:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
export MANGROVE_API_KEY=prod_your_key_here
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Quickstart
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from mangroveai import MangroveAI
|
|
57
|
+
|
|
58
|
+
client = MangroveAI() # reads MANGROVE_API_KEY from environment
|
|
59
|
+
|
|
60
|
+
# List trading signals
|
|
61
|
+
signals = client.signals.list(limit=10)
|
|
62
|
+
for s in signals.items:
|
|
63
|
+
print(f"{s.name} ({s.category}, {s.signal_type})")
|
|
64
|
+
|
|
65
|
+
# Get market data
|
|
66
|
+
btc = client.crypto_assets.get_market_data("BTC")
|
|
67
|
+
print(f"BTC: ${btc.data['current_price']:,.2f}")
|
|
68
|
+
|
|
69
|
+
# Create a strategy
|
|
70
|
+
from mangroveai.models import CreateStrategyRequest
|
|
71
|
+
|
|
72
|
+
strategy = client.strategies.create(CreateStrategyRequest(
|
|
73
|
+
name="RSI Momentum",
|
|
74
|
+
asset="BTC",
|
|
75
|
+
entry=[{"name": "rsi_oversold", "signal_type": "TRIGGER",
|
|
76
|
+
"timeframe": "1d", "params": {"window": 14, "threshold": 30}}],
|
|
77
|
+
))
|
|
78
|
+
|
|
79
|
+
# Run a backtest
|
|
80
|
+
import json
|
|
81
|
+
from mangroveai.models import BacktestRequest
|
|
82
|
+
|
|
83
|
+
result = client.backtesting.run(BacktestRequest(
|
|
84
|
+
asset="BTC",
|
|
85
|
+
interval="1d",
|
|
86
|
+
strategy_json=json.dumps({"name": "test", "asset": "BTC",
|
|
87
|
+
"entry": [{"name": "rsi_oversold", "signal_type": "TRIGGER",
|
|
88
|
+
"timeframe": "1d", "params": {"window": 14, "threshold": 30}}],
|
|
89
|
+
"exit": []}),
|
|
90
|
+
lookback_months=3,
|
|
91
|
+
initial_balance=10000,
|
|
92
|
+
min_balance_threshold=0.1, min_trade_amount=25,
|
|
93
|
+
max_open_positions=3, max_trades_per_day=10,
|
|
94
|
+
max_risk_per_trade=0.02, max_units_per_trade=1000000,
|
|
95
|
+
max_trade_amount=10000000, volatility_window=24,
|
|
96
|
+
target_volatility=0.1,
|
|
97
|
+
))
|
|
98
|
+
print(f"Trades: {result.trade_count}, Sharpe: {result.metrics.get('sharpe_ratio')}")
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Services
|
|
102
|
+
|
|
103
|
+
### Layer 1: MangroveAI Core API
|
|
104
|
+
|
|
105
|
+
| Service | Access | Methods | Description |
|
|
106
|
+
|---------|--------|---------|-------------|
|
|
107
|
+
| `client.auth` | `auth.*` | 5 | Login, refresh, API key management |
|
|
108
|
+
| `client.strategies` | `strategies.*` | 8 | Strategy CRUD, status, execution state |
|
|
109
|
+
| `client.backtesting` | `backtesting.*` | 7 | Sync/async/bulk backtesting |
|
|
110
|
+
| `client.signals` | `signals.*` | 7 | Signal discovery, evaluation, validation |
|
|
111
|
+
| `client.crypto_assets` | `crypto_assets.*` | 8 | Assets, exchanges, OHLCV, market data |
|
|
112
|
+
| `client.execution` | `execution.*` | 8 | Accounts, positions, trades, evaluation |
|
|
113
|
+
| `client.docs` | `docs.*` | 2 | Documentation listing and content |
|
|
114
|
+
|
|
115
|
+
### Layer 2: Knowledge Base API
|
|
116
|
+
|
|
117
|
+
| Service | Access | Methods | Description |
|
|
118
|
+
|---------|--------|---------|-------------|
|
|
119
|
+
| `client.kb.documents` | `kb.documents.*` | 3 | Document listing, content, sections |
|
|
120
|
+
| `client.kb.search` | `kb.search.*` | 1 | Full-text search with BM25 ranking |
|
|
121
|
+
| `client.kb.tags` | `kb.tags.*` | 2 | Tag listing and filtering |
|
|
122
|
+
| `client.kb.glossary` | `kb.glossary.*` | 3 | Glossary terms and backlinks |
|
|
123
|
+
| `client.kb.signals` | `kb.signals.*` | 2 | Signal metadata from KB |
|
|
124
|
+
| `client.kb.indicators` | `kb.indicators.*` | 2 | Indicator metadata from KB |
|
|
125
|
+
| `client.kb.compute` | `kb.compute.*` | 2 | x402 paid signal/indicator computation |
|
|
126
|
+
|
|
127
|
+
### Layer 3: Coming Soon
|
|
128
|
+
|
|
129
|
+
On-chain analytics (`client.on_chain`), DeFi data (`client.defi`), and social signals (`client.social`) are defined but not yet available. Calling these methods raises `NotImplementedLayerError`.
|
|
130
|
+
|
|
131
|
+
## Environment Detection
|
|
132
|
+
|
|
133
|
+
The SDK auto-detects the environment from your API key prefix:
|
|
134
|
+
|
|
135
|
+
| Prefix | Environment | API Base URL |
|
|
136
|
+
|--------|-------------|-------------|
|
|
137
|
+
| `prod_` | Production | `https://api.mangrovedeveloper.ai/api/v1` |
|
|
138
|
+
| `dev_` | Development | `https://devapi.mangrove.trade/api/v1` |
|
|
139
|
+
|
|
140
|
+
Override with explicit parameters:
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
client = MangroveAI(api_key="...", base_url="http://localhost:5001/api/v1")
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Error Handling
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
from mangroveai import MangroveAI, NotFoundError, RateLimitError, APIError
|
|
150
|
+
|
|
151
|
+
client = MangroveAI()
|
|
152
|
+
|
|
153
|
+
try:
|
|
154
|
+
strategy = client.strategies.get("nonexistent-id")
|
|
155
|
+
except NotFoundError as e:
|
|
156
|
+
print(f"Not found: {e.message} (correlation_id={e.correlation_id})")
|
|
157
|
+
except RateLimitError as e:
|
|
158
|
+
print(f"Rate limited, retry after {e.retry_after}s")
|
|
159
|
+
except APIError as e:
|
|
160
|
+
print(f"[{e.status_code}] {e.code}: {e.message}")
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Pagination
|
|
164
|
+
|
|
165
|
+
Paginated endpoints return `PaginatedResponse[T]`:
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
# Single page
|
|
169
|
+
page = client.strategies.list(skip=0, limit=10)
|
|
170
|
+
print(f"Showing {len(page.items)} of {page.total}")
|
|
171
|
+
|
|
172
|
+
# Auto-paginate all items
|
|
173
|
+
for strategy in client.strategies.list_iter():
|
|
174
|
+
print(strategy.name)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Examples
|
|
178
|
+
|
|
179
|
+
See the [`examples/`](examples/) directory for working scripts.
|
|
180
|
+
|
|
181
|
+
## Development
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
git clone https://github.com/MangroveTechnologies/MangroveAI-SDK.git
|
|
185
|
+
cd MangroveAI-SDK
|
|
186
|
+
pip install -e ".[dev]"
|
|
187
|
+
pytest tests/ --ignore=tests/integration # unit tests
|
|
188
|
+
MANGROVE_API_KEY=... pytest tests/integration/ -m integration # live tests
|
|
189
|
+
```
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# MangroveAI Python SDK
|
|
2
|
+
|
|
3
|
+
Python SDK for the [MangroveAI](https://mangrovedeveloper.ai) trading strategy platform.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install mangroveai
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
1. Create an account at [mangrovedeveloper.ai](https://mangrovedeveloper.ai)
|
|
14
|
+
2. Navigate to **Settings > API Keys**
|
|
15
|
+
3. Generate a new API key
|
|
16
|
+
4. Set it as an environment variable:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
export MANGROVE_API_KEY=prod_your_key_here
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quickstart
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
from mangroveai import MangroveAI
|
|
26
|
+
|
|
27
|
+
client = MangroveAI() # reads MANGROVE_API_KEY from environment
|
|
28
|
+
|
|
29
|
+
# List trading signals
|
|
30
|
+
signals = client.signals.list(limit=10)
|
|
31
|
+
for s in signals.items:
|
|
32
|
+
print(f"{s.name} ({s.category}, {s.signal_type})")
|
|
33
|
+
|
|
34
|
+
# Get market data
|
|
35
|
+
btc = client.crypto_assets.get_market_data("BTC")
|
|
36
|
+
print(f"BTC: ${btc.data['current_price']:,.2f}")
|
|
37
|
+
|
|
38
|
+
# Create a strategy
|
|
39
|
+
from mangroveai.models import CreateStrategyRequest
|
|
40
|
+
|
|
41
|
+
strategy = client.strategies.create(CreateStrategyRequest(
|
|
42
|
+
name="RSI Momentum",
|
|
43
|
+
asset="BTC",
|
|
44
|
+
entry=[{"name": "rsi_oversold", "signal_type": "TRIGGER",
|
|
45
|
+
"timeframe": "1d", "params": {"window": 14, "threshold": 30}}],
|
|
46
|
+
))
|
|
47
|
+
|
|
48
|
+
# Run a backtest
|
|
49
|
+
import json
|
|
50
|
+
from mangroveai.models import BacktestRequest
|
|
51
|
+
|
|
52
|
+
result = client.backtesting.run(BacktestRequest(
|
|
53
|
+
asset="BTC",
|
|
54
|
+
interval="1d",
|
|
55
|
+
strategy_json=json.dumps({"name": "test", "asset": "BTC",
|
|
56
|
+
"entry": [{"name": "rsi_oversold", "signal_type": "TRIGGER",
|
|
57
|
+
"timeframe": "1d", "params": {"window": 14, "threshold": 30}}],
|
|
58
|
+
"exit": []}),
|
|
59
|
+
lookback_months=3,
|
|
60
|
+
initial_balance=10000,
|
|
61
|
+
min_balance_threshold=0.1, min_trade_amount=25,
|
|
62
|
+
max_open_positions=3, max_trades_per_day=10,
|
|
63
|
+
max_risk_per_trade=0.02, max_units_per_trade=1000000,
|
|
64
|
+
max_trade_amount=10000000, volatility_window=24,
|
|
65
|
+
target_volatility=0.1,
|
|
66
|
+
))
|
|
67
|
+
print(f"Trades: {result.trade_count}, Sharpe: {result.metrics.get('sharpe_ratio')}")
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Services
|
|
71
|
+
|
|
72
|
+
### Layer 1: MangroveAI Core API
|
|
73
|
+
|
|
74
|
+
| Service | Access | Methods | Description |
|
|
75
|
+
|---------|--------|---------|-------------|
|
|
76
|
+
| `client.auth` | `auth.*` | 5 | Login, refresh, API key management |
|
|
77
|
+
| `client.strategies` | `strategies.*` | 8 | Strategy CRUD, status, execution state |
|
|
78
|
+
| `client.backtesting` | `backtesting.*` | 7 | Sync/async/bulk backtesting |
|
|
79
|
+
| `client.signals` | `signals.*` | 7 | Signal discovery, evaluation, validation |
|
|
80
|
+
| `client.crypto_assets` | `crypto_assets.*` | 8 | Assets, exchanges, OHLCV, market data |
|
|
81
|
+
| `client.execution` | `execution.*` | 8 | Accounts, positions, trades, evaluation |
|
|
82
|
+
| `client.docs` | `docs.*` | 2 | Documentation listing and content |
|
|
83
|
+
|
|
84
|
+
### Layer 2: Knowledge Base API
|
|
85
|
+
|
|
86
|
+
| Service | Access | Methods | Description |
|
|
87
|
+
|---------|--------|---------|-------------|
|
|
88
|
+
| `client.kb.documents` | `kb.documents.*` | 3 | Document listing, content, sections |
|
|
89
|
+
| `client.kb.search` | `kb.search.*` | 1 | Full-text search with BM25 ranking |
|
|
90
|
+
| `client.kb.tags` | `kb.tags.*` | 2 | Tag listing and filtering |
|
|
91
|
+
| `client.kb.glossary` | `kb.glossary.*` | 3 | Glossary terms and backlinks |
|
|
92
|
+
| `client.kb.signals` | `kb.signals.*` | 2 | Signal metadata from KB |
|
|
93
|
+
| `client.kb.indicators` | `kb.indicators.*` | 2 | Indicator metadata from KB |
|
|
94
|
+
| `client.kb.compute` | `kb.compute.*` | 2 | x402 paid signal/indicator computation |
|
|
95
|
+
|
|
96
|
+
### Layer 3: Coming Soon
|
|
97
|
+
|
|
98
|
+
On-chain analytics (`client.on_chain`), DeFi data (`client.defi`), and social signals (`client.social`) are defined but not yet available. Calling these methods raises `NotImplementedLayerError`.
|
|
99
|
+
|
|
100
|
+
## Environment Detection
|
|
101
|
+
|
|
102
|
+
The SDK auto-detects the environment from your API key prefix:
|
|
103
|
+
|
|
104
|
+
| Prefix | Environment | API Base URL |
|
|
105
|
+
|--------|-------------|-------------|
|
|
106
|
+
| `prod_` | Production | `https://api.mangrovedeveloper.ai/api/v1` |
|
|
107
|
+
| `dev_` | Development | `https://devapi.mangrove.trade/api/v1` |
|
|
108
|
+
|
|
109
|
+
Override with explicit parameters:
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
client = MangroveAI(api_key="...", base_url="http://localhost:5001/api/v1")
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Error Handling
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
from mangroveai import MangroveAI, NotFoundError, RateLimitError, APIError
|
|
119
|
+
|
|
120
|
+
client = MangroveAI()
|
|
121
|
+
|
|
122
|
+
try:
|
|
123
|
+
strategy = client.strategies.get("nonexistent-id")
|
|
124
|
+
except NotFoundError as e:
|
|
125
|
+
print(f"Not found: {e.message} (correlation_id={e.correlation_id})")
|
|
126
|
+
except RateLimitError as e:
|
|
127
|
+
print(f"Rate limited, retry after {e.retry_after}s")
|
|
128
|
+
except APIError as e:
|
|
129
|
+
print(f"[{e.status_code}] {e.code}: {e.message}")
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Pagination
|
|
133
|
+
|
|
134
|
+
Paginated endpoints return `PaginatedResponse[T]`:
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
# Single page
|
|
138
|
+
page = client.strategies.list(skip=0, limit=10)
|
|
139
|
+
print(f"Showing {len(page.items)} of {page.total}")
|
|
140
|
+
|
|
141
|
+
# Auto-paginate all items
|
|
142
|
+
for strategy in client.strategies.list_iter():
|
|
143
|
+
print(strategy.name)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Examples
|
|
147
|
+
|
|
148
|
+
See the [`examples/`](examples/) directory for working scripts.
|
|
149
|
+
|
|
150
|
+
## Development
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
git clone https://github.com/MangroveTechnologies/MangroveAI-SDK.git
|
|
154
|
+
cd MangroveAI-SDK
|
|
155
|
+
pip install -e ".[dev]"
|
|
156
|
+
pytest tests/ --ignore=tests/integration # unit tests
|
|
157
|
+
MANGROVE_API_KEY=... pytest tests/integration/ -m integration # live tests
|
|
158
|
+
```
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"""MangroveAI SDK Quickstart
|
|
2
|
+
|
|
3
|
+
Getting started:
|
|
4
|
+
1. Create an account at https://mangrovedeveloper.ai
|
|
5
|
+
2. Navigate to Settings > API Keys
|
|
6
|
+
3. Generate a new API key
|
|
7
|
+
4. Set it as an environment variable:
|
|
8
|
+
export MANGROVE_API_KEY=prod_your_key_here
|
|
9
|
+
|
|
10
|
+
Then run this script:
|
|
11
|
+
python examples/quickstart.py
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from mangroveai import MangroveAI
|
|
15
|
+
from mangroveai.models import CreateStrategyRequest, BacktestRequest
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def main() -> None:
|
|
19
|
+
# Initialize client -- reads MANGROVE_API_KEY from environment
|
|
20
|
+
# Auto-detects prod/dev from key prefix
|
|
21
|
+
client = MangroveAI()
|
|
22
|
+
|
|
23
|
+
# ---- Signals ----
|
|
24
|
+
# List available trading signals
|
|
25
|
+
signals = client.signals.list(limit=10)
|
|
26
|
+
print(f"Available signals: {signals.total}")
|
|
27
|
+
for s in signals.items[:5]:
|
|
28
|
+
print(f" {s.name} ({s.category}, {s.signal_type})")
|
|
29
|
+
|
|
30
|
+
# Search for specific signals
|
|
31
|
+
from mangroveai.models import SearchSignalsRequest
|
|
32
|
+
results = client.signals.search(SearchSignalsRequest(query="rsi", search_type="name"))
|
|
33
|
+
print(f"\nRSI signals: {results.total}")
|
|
34
|
+
for s in results.items:
|
|
35
|
+
print(f" {s.name}")
|
|
36
|
+
|
|
37
|
+
# Get signal details
|
|
38
|
+
rsi = client.signals.get("rsi_oversold")
|
|
39
|
+
print(f"\n{rsi.name}: {rsi.metadata.description}")
|
|
40
|
+
print(f" Params: {rsi.metadata.params}")
|
|
41
|
+
|
|
42
|
+
# ---- Market Data ----
|
|
43
|
+
# Current price and market data
|
|
44
|
+
btc = client.crypto_assets.get_market_data("BTC")
|
|
45
|
+
print(f"\nBTC price: ${btc.data['current_price']:,.2f}")
|
|
46
|
+
print(f" Market cap: ${btc.data['market_cap']:,.0f}")
|
|
47
|
+
print(f" 24h volume: ${btc.data['volume_24h']:,.0f}")
|
|
48
|
+
|
|
49
|
+
# Global market overview
|
|
50
|
+
global_data = client.crypto_assets.get_global_market()
|
|
51
|
+
print(f"\nGlobal market cap: ${global_data.data['total_market_cap_usd']:,.0f}")
|
|
52
|
+
print(f" BTC dominance: {global_data.data['btc_dominance']:.1f}%")
|
|
53
|
+
|
|
54
|
+
# ---- Strategies ----
|
|
55
|
+
# Create a strategy
|
|
56
|
+
strategy = client.strategies.create(CreateStrategyRequest(
|
|
57
|
+
name="SDK Quickstart - RSI Momentum",
|
|
58
|
+
asset="BTC",
|
|
59
|
+
strategy_type="momentum",
|
|
60
|
+
description="Buys BTC when RSI crosses below 30 while price is above 50-period SMA",
|
|
61
|
+
entry=[
|
|
62
|
+
{"name": "rsi_oversold", "signal_type": "TRIGGER", "timeframe": "1d", "params": {"window": 14, "threshold": 30}},
|
|
63
|
+
{"name": "is_above_sma", "signal_type": "FILTER", "timeframe": "1d", "params": {"window": 50}},
|
|
64
|
+
],
|
|
65
|
+
exit=[],
|
|
66
|
+
reward_factor=2.0,
|
|
67
|
+
))
|
|
68
|
+
print(f"\nCreated strategy: {strategy.name} (id={strategy.id})")
|
|
69
|
+
|
|
70
|
+
# ---- Backtesting ----
|
|
71
|
+
# Backtest the strategy
|
|
72
|
+
import json
|
|
73
|
+
result = client.backtesting.run(BacktestRequest(
|
|
74
|
+
asset="BTC",
|
|
75
|
+
interval="1d",
|
|
76
|
+
strategy_json=json.dumps({
|
|
77
|
+
"name": strategy.name,
|
|
78
|
+
"asset": "BTC",
|
|
79
|
+
"entry": [
|
|
80
|
+
{"name": "rsi_oversold", "signal_type": "TRIGGER", "timeframe": "1d", "params": {"window": 14, "threshold": 30}},
|
|
81
|
+
{"name": "is_above_sma", "signal_type": "FILTER", "timeframe": "1d", "params": {"window": 50}},
|
|
82
|
+
],
|
|
83
|
+
"exit": [],
|
|
84
|
+
}),
|
|
85
|
+
lookback_months=3,
|
|
86
|
+
initial_balance=10000,
|
|
87
|
+
min_balance_threshold=0.1,
|
|
88
|
+
min_trade_amount=25,
|
|
89
|
+
max_open_positions=3,
|
|
90
|
+
max_trades_per_day=10,
|
|
91
|
+
max_risk_per_trade=0.02,
|
|
92
|
+
max_units_per_trade=1000000,
|
|
93
|
+
max_trade_amount=10000000,
|
|
94
|
+
volatility_window=24,
|
|
95
|
+
target_volatility=0.1,
|
|
96
|
+
))
|
|
97
|
+
|
|
98
|
+
if result.success:
|
|
99
|
+
print(f"\nBacktest results ({result.trade_count} trades):")
|
|
100
|
+
for key, value in (result.metrics or {}).items():
|
|
101
|
+
if isinstance(value, float):
|
|
102
|
+
print(f" {key}: {value:.4f}")
|
|
103
|
+
else:
|
|
104
|
+
print(f" {key}: {value}")
|
|
105
|
+
else:
|
|
106
|
+
print(f"\nBacktest failed: {result.error}")
|
|
107
|
+
|
|
108
|
+
# ---- Cleanup ----
|
|
109
|
+
try:
|
|
110
|
+
client.strategies.delete(strategy.id)
|
|
111
|
+
print(f"\nCleaned up strategy {strategy.id}")
|
|
112
|
+
except Exception as e:
|
|
113
|
+
print(f"\nNote: could not delete strategy (may require strategy:delete permission): {e}")
|
|
114
|
+
|
|
115
|
+
client.close()
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
if __name__ == "__main__":
|
|
119
|
+
main()
|