ocean-agent 0.3.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.
- ocean_agent-0.3.0/LICENSE +21 -0
- ocean_agent-0.3.0/PKG-INFO +202 -0
- ocean_agent-0.3.0/README.md +185 -0
- ocean_agent-0.3.0/ocean_agent/__init__.py +133 -0
- ocean_agent-0.3.0/ocean_agent/advisor.py +210 -0
- ocean_agent-0.3.0/ocean_agent/api_client.py +327 -0
- ocean_agent-0.3.0/ocean_agent/autonomous.py +1390 -0
- ocean_agent-0.3.0/ocean_agent/backtest.py +181 -0
- ocean_agent-0.3.0/ocean_agent/brain.py +181 -0
- ocean_agent-0.3.0/ocean_agent/curve_seed.json +831 -0
- ocean_agent-0.3.0/ocean_agent/doctor.py +100 -0
- ocean_agent-0.3.0/ocean_agent/harness.py +690 -0
- ocean_agent-0.3.0/ocean_agent/historical_data.py +453 -0
- ocean_agent-0.3.0/ocean_agent/indicators.py +378 -0
- ocean_agent-0.3.0/ocean_agent/main.py +214 -0
- ocean_agent-0.3.0/ocean_agent/market_context.py +112 -0
- ocean_agent-0.3.0/ocean_agent/matrix_seed.json +1 -0
- ocean_agent-0.3.0/ocean_agent/mcp_client.py +164 -0
- ocean_agent-0.3.0/ocean_agent/mcp_server.py +833 -0
- ocean_agent-0.3.0/ocean_agent/notify.py +21 -0
- ocean_agent-0.3.0/ocean_agent/observer.py +396 -0
- ocean_agent-0.3.0/ocean_agent/oi_planner.py +121 -0
- ocean_agent-0.3.0/ocean_agent/policy_default.yaml +136 -0
- ocean_agent-0.3.0/ocean_agent/position.py +130 -0
- ocean_agent-0.3.0/ocean_agent/postmortem.py +174 -0
- ocean_agent-0.3.0/ocean_agent/print_eval.py +547 -0
- ocean_agent-0.3.0/ocean_agent/rematrix.py +561 -0
- ocean_agent-0.3.0/ocean_agent/scanner.py +136 -0
- ocean_agent-0.3.0/ocean_agent/signal_scanner.py +912 -0
- ocean_agent-0.3.0/ocean_agent/signing.py +44 -0
- ocean_agent-0.3.0/ocean_agent/state.py +23 -0
- ocean_agent-0.3.0/ocean_agent/walkforward.py +603 -0
- ocean_agent-0.3.0/ocean_agent.egg-info/PKG-INFO +202 -0
- ocean_agent-0.3.0/ocean_agent.egg-info/SOURCES.txt +38 -0
- ocean_agent-0.3.0/ocean_agent.egg-info/dependency_links.txt +1 -0
- ocean_agent-0.3.0/ocean_agent.egg-info/entry_points.txt +2 -0
- ocean_agent-0.3.0/ocean_agent.egg-info/requires.txt +6 -0
- ocean_agent-0.3.0/ocean_agent.egg-info/top_level.txt +1 -0
- ocean_agent-0.3.0/pyproject.toml +33 -0
- ocean_agent-0.3.0/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 mustache-mcp / Ocean Agent contributors
|
|
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,202 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ocean-agent
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Pacifica trading MCP server — measured-edge setups, exchange-native brackets, funding carry, and a policy-governed autonomous trading entity
|
|
5
|
+
License: MIT
|
|
6
|
+
Keywords: mcp,pacifica,trading,funding-rate,delta-neutral,solana
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: requests>=2.31.0
|
|
11
|
+
Requires-Dist: solders>=0.19.0
|
|
12
|
+
Requires-Dist: base58>=2.1.1
|
|
13
|
+
Requires-Dist: PyYAML>=6.0
|
|
14
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
15
|
+
Requires-Dist: mcp<2,>=1.0
|
|
16
|
+
Dynamic: license-file
|
|
17
|
+
|
|
18
|
+
# ocean-agent
|
|
19
|
+
|
|
20
|
+
> English · [한국어](README.ko.md)
|
|
21
|
+
|
|
22
|
+
**Tell your AI to trade.** An MCP server for [Pacifica](https://app.pacifica.fi)
|
|
23
|
+
that turns natural language into correct, risk-sized perpetual futures orders —
|
|
24
|
+
plus a 24/7 autonomous trading entity governed by a policy file you control.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
uvx ocean-agent # no install needed
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
> ⚠️ This places real orders with real money. Read the
|
|
31
|
+
> [disclaimer](DISCLAIMER.md) before connecting an account.
|
|
32
|
+
|
|
33
|
+
Built entirely on Pacifica. Calls the Pacifica REST API directly with the same
|
|
34
|
+
Ed25519 agent-key signing the official tooling uses — no npm dependency.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Why this instead of raw API access
|
|
39
|
+
|
|
40
|
+
The official Pacifica MCP exposes the API as-is: your AI must compute exact
|
|
41
|
+
prices and sizes itself, and a price that isn't a multiple of the market's tick
|
|
42
|
+
size is rejected by the exchange. ocean-agent adds the layer above that:
|
|
43
|
+
|
|
44
|
+
| | Raw API / official MCP | ocean-agent |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| Order prices | AI computes exact values | Say *"3% stop"* — tick/lot/min-order corrected automatically |
|
|
47
|
+
| Position sizing | Manual | Risk-based (fixed % of capital at risk per trade) |
|
|
48
|
+
| Safety | None | Two-step confirm gate on every money-moving tool |
|
|
49
|
+
| Statistics | None | Measured win rates and expected value, not textbook theory |
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## MCP tools
|
|
54
|
+
|
|
55
|
+
**Market & analysis**
|
|
56
|
+
- `analyze_chart` — multi-timeframe indicator snapshot with *measured* hit rates
|
|
57
|
+
per signal on that specific coin and timeframe. Says "no edge detected" when
|
|
58
|
+
there isn't one.
|
|
59
|
+
- `top_setups` — live ranking of statistically-proven setups (EV × win rate ×
|
|
60
|
+
sample confidence), with entry, stop, target and leverage
|
|
61
|
+
- `market_context` — Fear & Greed regime read
|
|
62
|
+
- `scan_funding` — every market ranked by funding APR
|
|
63
|
+
- `learned_winrates` / `learned_combos` — win-rate database built from live
|
|
64
|
+
observation, including multi-signal combinations
|
|
65
|
+
- `review_predictions` — past calls graded against what actually happened
|
|
66
|
+
|
|
67
|
+
**Trading**
|
|
68
|
+
- `open_with_bracket` — entry plus exchange-native TP/SL in one call. The stops
|
|
69
|
+
live on the exchange, so they fire even with your machine off.
|
|
70
|
+
- `protect_position` — retrofit native TP/SL onto any open position
|
|
71
|
+
- `open_funding_position` / `close_funding_position` — delta-neutral funding
|
|
72
|
+
carry (spot buy + perp short) executed atomically as a batch
|
|
73
|
+
- `plan_oi_hedge` — sizes an OI-farming position with its cross-exchange hedge,
|
|
74
|
+
fee and funding math included
|
|
75
|
+
- `open_pacifica_leg`, `check_position`, `account_status`
|
|
76
|
+
|
|
77
|
+
**Print** (experimental — uses an endpoint Pacifica has not documented; may
|
|
78
|
+
change without notice)
|
|
79
|
+
- `print_quote` — live premium, implied volatility and liquidation price
|
|
80
|
+
- `print_order` / `print_status` / `print_close`
|
|
81
|
+
- `evaluate_print` — statistical verdict on whether a Print offer is worth it:
|
|
82
|
+
fill probability, average overshoot, and the breakeven APY that would
|
|
83
|
+
compensate for it
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Autonomous trading entity
|
|
88
|
+
|
|
89
|
+
A self-directed trader governed by `policy.yaml` — a delegation contract. It
|
|
90
|
+
cannot act outside those bounds.
|
|
91
|
+
|
|
92
|
+
This is a **separate always-on process**, not an MCP tool. An MCP server only
|
|
93
|
+
runs when your AI client calls it; a trader that must hold positions and manage
|
|
94
|
+
stops around the clock needs its own process. Start it deliberately, and it
|
|
95
|
+
keeps running whether or not any AI is connected.
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
python -m ocean_agent.autonomous --init # create policy.yaml to edit
|
|
99
|
+
python -m ocean_agent.autonomous --dry # decide, but place no orders
|
|
100
|
+
python -m ocean_agent.autonomous # run continuously
|
|
101
|
+
python -m ocean_agent.autonomous --once # single cycle
|
|
102
|
+
python -m ocean_agent.autonomous --report # performance summary
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Read `policy.yaml` before the first real run — capital, leverage cap, risk per
|
|
106
|
+
trade and the hard-stop threshold all live there. Start with `--dry` on testnet.
|
|
107
|
+
|
|
108
|
+
Each cycle it reads the market, grades what it learned, manages open positions,
|
|
109
|
+
and enters only setups that clear every gate.
|
|
110
|
+
|
|
111
|
+
**Portfolio buckets** — capital split across directional trading, funding carry
|
|
112
|
+
and a cash reserve, rebalanced every cycle.
|
|
113
|
+
|
|
114
|
+
**Position aftercare** — moves the stop to breakeven once a trade is ahead,
|
|
115
|
+
trails it as profit grows, and takes partial profit at target. Stops only ever
|
|
116
|
+
move in your favour.
|
|
117
|
+
|
|
118
|
+
**Liquidity gate** — skips markets where your own order would be a large share
|
|
119
|
+
of daily volume. Thin books are the real hazard: an order that only partly
|
|
120
|
+
fills, and a stop that cannot be executed at its price.
|
|
121
|
+
|
|
122
|
+
**Net-exposure limit** — caps how one-directional the book can get, so a single
|
|
123
|
+
market reversal cannot hit every position at once.
|
|
124
|
+
|
|
125
|
+
**Self-remeasurement** — this is the actual learning engine. On a schedule the
|
|
126
|
+
bot re-measures the full matrix of coins × timeframes × signals and updates
|
|
127
|
+
which timeframes it trades and which signals it trusts. Regimes change: in one
|
|
128
|
+
measurement the 8h timeframe showed no edge at all; weeks later it was the
|
|
129
|
+
best-performing band. Fixed parameters go stale, so they are not fixed.
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
python -m ocean_agent.rematrix # remeasure now
|
|
133
|
+
python -m ocean_agent.rematrix --show # what it currently believes
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Adaptation** — signals that lose in live grading are suspended, size is cut
|
|
137
|
+
during drawdown and restored on recovery. Parameters adapt within policy bounds;
|
|
138
|
+
the bot never rewrites its own code.
|
|
139
|
+
|
|
140
|
+
**Final stop** — a single hard halt at catastrophic loss. Otherwise it does not
|
|
141
|
+
stop, it adapts.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Setup
|
|
146
|
+
|
|
147
|
+
Requires Python 3.10+.
|
|
148
|
+
|
|
149
|
+
1. Create an **agent wallet key** at [app.pacifica.fi/apikey](https://app.pacifica.fi/apikey).
|
|
150
|
+
API keys can trade but **cannot withdraw funds**, and you can revoke them
|
|
151
|
+
at any time.
|
|
152
|
+
|
|
153
|
+
2. Put it in `.env`:
|
|
154
|
+
|
|
155
|
+
```ini
|
|
156
|
+
ADDRESS=your_main_wallet_address
|
|
157
|
+
PACIFICA_API_KEY=your_agent_wallet_key
|
|
158
|
+
|
|
159
|
+
# optional — testnet uses separate keys
|
|
160
|
+
ADDRESS_TESTNET=...
|
|
161
|
+
PACIFICA_API_KEY_TESTNET=...
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
3. Point your MCP client at it:
|
|
165
|
+
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"mcpServers": {
|
|
169
|
+
"ocean-agent": {
|
|
170
|
+
"command": "uvx",
|
|
171
|
+
"args": ["ocean-agent"],
|
|
172
|
+
"env": { "PACIFICA_ENV_FILE": "/absolute/path/to/.env" }
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Defaults to testnet. Set `PACIFICA_BASE_URL=https://api.pacifica.fi` for live
|
|
179
|
+
trading.
|
|
180
|
+
|
|
181
|
+
Check your setup with `python -m ocean_agent.doctor`.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Safety
|
|
186
|
+
|
|
187
|
+
- API keys are trading-only — this software cannot move your funds out
|
|
188
|
+
- Every order tool previews first and executes only on explicit confirmation
|
|
189
|
+
- Testnet and mainnet keys are kept separate
|
|
190
|
+
- The autonomous entity acts only within `policy.yaml`
|
|
191
|
+
|
|
192
|
+
## Risk
|
|
193
|
+
|
|
194
|
+
This is trading software. Leveraged perpetual futures can lose more than the
|
|
195
|
+
margin you post. Measured win rates come from historical data and are
|
|
196
|
+
regime-dependent — an edge that held for months can vanish when the market
|
|
197
|
+
changes character. Nothing here is financial advice. Run it on testnet until
|
|
198
|
+
you understand exactly what it does, and only risk what you can afford to lose.
|
|
199
|
+
|
|
200
|
+
## License
|
|
201
|
+
|
|
202
|
+
MIT
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# ocean-agent
|
|
2
|
+
|
|
3
|
+
> English · [한국어](README.ko.md)
|
|
4
|
+
|
|
5
|
+
**Tell your AI to trade.** An MCP server for [Pacifica](https://app.pacifica.fi)
|
|
6
|
+
that turns natural language into correct, risk-sized perpetual futures orders —
|
|
7
|
+
plus a 24/7 autonomous trading entity governed by a policy file you control.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
uvx ocean-agent # no install needed
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
> ⚠️ This places real orders with real money. Read the
|
|
14
|
+
> [disclaimer](DISCLAIMER.md) before connecting an account.
|
|
15
|
+
|
|
16
|
+
Built entirely on Pacifica. Calls the Pacifica REST API directly with the same
|
|
17
|
+
Ed25519 agent-key signing the official tooling uses — no npm dependency.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Why this instead of raw API access
|
|
22
|
+
|
|
23
|
+
The official Pacifica MCP exposes the API as-is: your AI must compute exact
|
|
24
|
+
prices and sizes itself, and a price that isn't a multiple of the market's tick
|
|
25
|
+
size is rejected by the exchange. ocean-agent adds the layer above that:
|
|
26
|
+
|
|
27
|
+
| | Raw API / official MCP | ocean-agent |
|
|
28
|
+
|---|---|---|
|
|
29
|
+
| Order prices | AI computes exact values | Say *"3% stop"* — tick/lot/min-order corrected automatically |
|
|
30
|
+
| Position sizing | Manual | Risk-based (fixed % of capital at risk per trade) |
|
|
31
|
+
| Safety | None | Two-step confirm gate on every money-moving tool |
|
|
32
|
+
| Statistics | None | Measured win rates and expected value, not textbook theory |
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## MCP tools
|
|
37
|
+
|
|
38
|
+
**Market & analysis**
|
|
39
|
+
- `analyze_chart` — multi-timeframe indicator snapshot with *measured* hit rates
|
|
40
|
+
per signal on that specific coin and timeframe. Says "no edge detected" when
|
|
41
|
+
there isn't one.
|
|
42
|
+
- `top_setups` — live ranking of statistically-proven setups (EV × win rate ×
|
|
43
|
+
sample confidence), with entry, stop, target and leverage
|
|
44
|
+
- `market_context` — Fear & Greed regime read
|
|
45
|
+
- `scan_funding` — every market ranked by funding APR
|
|
46
|
+
- `learned_winrates` / `learned_combos` — win-rate database built from live
|
|
47
|
+
observation, including multi-signal combinations
|
|
48
|
+
- `review_predictions` — past calls graded against what actually happened
|
|
49
|
+
|
|
50
|
+
**Trading**
|
|
51
|
+
- `open_with_bracket` — entry plus exchange-native TP/SL in one call. The stops
|
|
52
|
+
live on the exchange, so they fire even with your machine off.
|
|
53
|
+
- `protect_position` — retrofit native TP/SL onto any open position
|
|
54
|
+
- `open_funding_position` / `close_funding_position` — delta-neutral funding
|
|
55
|
+
carry (spot buy + perp short) executed atomically as a batch
|
|
56
|
+
- `plan_oi_hedge` — sizes an OI-farming position with its cross-exchange hedge,
|
|
57
|
+
fee and funding math included
|
|
58
|
+
- `open_pacifica_leg`, `check_position`, `account_status`
|
|
59
|
+
|
|
60
|
+
**Print** (experimental — uses an endpoint Pacifica has not documented; may
|
|
61
|
+
change without notice)
|
|
62
|
+
- `print_quote` — live premium, implied volatility and liquidation price
|
|
63
|
+
- `print_order` / `print_status` / `print_close`
|
|
64
|
+
- `evaluate_print` — statistical verdict on whether a Print offer is worth it:
|
|
65
|
+
fill probability, average overshoot, and the breakeven APY that would
|
|
66
|
+
compensate for it
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Autonomous trading entity
|
|
71
|
+
|
|
72
|
+
A self-directed trader governed by `policy.yaml` — a delegation contract. It
|
|
73
|
+
cannot act outside those bounds.
|
|
74
|
+
|
|
75
|
+
This is a **separate always-on process**, not an MCP tool. An MCP server only
|
|
76
|
+
runs when your AI client calls it; a trader that must hold positions and manage
|
|
77
|
+
stops around the clock needs its own process. Start it deliberately, and it
|
|
78
|
+
keeps running whether or not any AI is connected.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
python -m ocean_agent.autonomous --init # create policy.yaml to edit
|
|
82
|
+
python -m ocean_agent.autonomous --dry # decide, but place no orders
|
|
83
|
+
python -m ocean_agent.autonomous # run continuously
|
|
84
|
+
python -m ocean_agent.autonomous --once # single cycle
|
|
85
|
+
python -m ocean_agent.autonomous --report # performance summary
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Read `policy.yaml` before the first real run — capital, leverage cap, risk per
|
|
89
|
+
trade and the hard-stop threshold all live there. Start with `--dry` on testnet.
|
|
90
|
+
|
|
91
|
+
Each cycle it reads the market, grades what it learned, manages open positions,
|
|
92
|
+
and enters only setups that clear every gate.
|
|
93
|
+
|
|
94
|
+
**Portfolio buckets** — capital split across directional trading, funding carry
|
|
95
|
+
and a cash reserve, rebalanced every cycle.
|
|
96
|
+
|
|
97
|
+
**Position aftercare** — moves the stop to breakeven once a trade is ahead,
|
|
98
|
+
trails it as profit grows, and takes partial profit at target. Stops only ever
|
|
99
|
+
move in your favour.
|
|
100
|
+
|
|
101
|
+
**Liquidity gate** — skips markets where your own order would be a large share
|
|
102
|
+
of daily volume. Thin books are the real hazard: an order that only partly
|
|
103
|
+
fills, and a stop that cannot be executed at its price.
|
|
104
|
+
|
|
105
|
+
**Net-exposure limit** — caps how one-directional the book can get, so a single
|
|
106
|
+
market reversal cannot hit every position at once.
|
|
107
|
+
|
|
108
|
+
**Self-remeasurement** — this is the actual learning engine. On a schedule the
|
|
109
|
+
bot re-measures the full matrix of coins × timeframes × signals and updates
|
|
110
|
+
which timeframes it trades and which signals it trusts. Regimes change: in one
|
|
111
|
+
measurement the 8h timeframe showed no edge at all; weeks later it was the
|
|
112
|
+
best-performing band. Fixed parameters go stale, so they are not fixed.
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
python -m ocean_agent.rematrix # remeasure now
|
|
116
|
+
python -m ocean_agent.rematrix --show # what it currently believes
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Adaptation** — signals that lose in live grading are suspended, size is cut
|
|
120
|
+
during drawdown and restored on recovery. Parameters adapt within policy bounds;
|
|
121
|
+
the bot never rewrites its own code.
|
|
122
|
+
|
|
123
|
+
**Final stop** — a single hard halt at catastrophic loss. Otherwise it does not
|
|
124
|
+
stop, it adapts.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Setup
|
|
129
|
+
|
|
130
|
+
Requires Python 3.10+.
|
|
131
|
+
|
|
132
|
+
1. Create an **agent wallet key** at [app.pacifica.fi/apikey](https://app.pacifica.fi/apikey).
|
|
133
|
+
API keys can trade but **cannot withdraw funds**, and you can revoke them
|
|
134
|
+
at any time.
|
|
135
|
+
|
|
136
|
+
2. Put it in `.env`:
|
|
137
|
+
|
|
138
|
+
```ini
|
|
139
|
+
ADDRESS=your_main_wallet_address
|
|
140
|
+
PACIFICA_API_KEY=your_agent_wallet_key
|
|
141
|
+
|
|
142
|
+
# optional — testnet uses separate keys
|
|
143
|
+
ADDRESS_TESTNET=...
|
|
144
|
+
PACIFICA_API_KEY_TESTNET=...
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
3. Point your MCP client at it:
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"mcpServers": {
|
|
152
|
+
"ocean-agent": {
|
|
153
|
+
"command": "uvx",
|
|
154
|
+
"args": ["ocean-agent"],
|
|
155
|
+
"env": { "PACIFICA_ENV_FILE": "/absolute/path/to/.env" }
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Defaults to testnet. Set `PACIFICA_BASE_URL=https://api.pacifica.fi` for live
|
|
162
|
+
trading.
|
|
163
|
+
|
|
164
|
+
Check your setup with `python -m ocean_agent.doctor`.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Safety
|
|
169
|
+
|
|
170
|
+
- API keys are trading-only — this software cannot move your funds out
|
|
171
|
+
- Every order tool previews first and executes only on explicit confirmation
|
|
172
|
+
- Testnet and mainnet keys are kept separate
|
|
173
|
+
- The autonomous entity acts only within `policy.yaml`
|
|
174
|
+
|
|
175
|
+
## Risk
|
|
176
|
+
|
|
177
|
+
This is trading software. Leveraged perpetual futures can lose more than the
|
|
178
|
+
margin you post. Measured win rates come from historical data and are
|
|
179
|
+
regime-dependent — an edge that held for months can vanish when the market
|
|
180
|
+
changes character. Nothing here is financial advice. Run it on testnet until
|
|
181
|
+
you understand exactly what it does, and only risk what you can afford to lose.
|
|
182
|
+
|
|
183
|
+
## License
|
|
184
|
+
|
|
185
|
+
MIT
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def _is_testnet(base_url: str) -> bool:
|
|
5
|
+
return "test-api" in base_url
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def data_tag() -> str:
|
|
9
|
+
"""라이브 계좌 데이터의 네임스페이스: 'testnet' vs 'mainnet'.
|
|
10
|
+
|
|
11
|
+
두 네트워크의 실매매 기록(상태·관측·승률·calibration·postmortem·예측·로그)이
|
|
12
|
+
절대 섞이지 않도록 파일을 분리한다. 판단 기준은 PACIFICA_BASE_URL 환경변수
|
|
13
|
+
(MCP는 .mcp.json이, 자율 개체는 시작 시 policy의 base_url로 설정)이며,
|
|
14
|
+
알 수 없으면 안전하게 'testnet'으로 본다.
|
|
15
|
+
MUSTACHE_DATA_TAG 로 강제 지정하면 그것이 최우선(멀티 인스턴스 격리용)."""
|
|
16
|
+
override = os.environ.get("MUSTACHE_DATA_TAG")
|
|
17
|
+
if override:
|
|
18
|
+
return override
|
|
19
|
+
base = os.environ.get("PACIFICA_BASE_URL", "")
|
|
20
|
+
return "mainnet" if (base and "test-api" not in base) else "testnet"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def data_file(name: str) -> str:
|
|
24
|
+
"""네트워크별 라이브 데이터 파일의 홈 경로를 돌려준다.
|
|
25
|
+
|
|
26
|
+
예) data_file("autonomous.json") -> ~/.ocean_agent_testnet_autonomous.json
|
|
27
|
+
시장 백테스트 매트릭스는 네트워크와 무관(가격 히스토리)하므로 여기 쓰지 않고
|
|
28
|
+
~/.ocean_agent_matrix.json 하나로 공유한다."""
|
|
29
|
+
return os.path.join(os.path.expanduser("~"),
|
|
30
|
+
f".ocean_agent_{data_tag()}_{name}")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# Mainnet-only brand name. Testnet keeps the original generic label so the
|
|
34
|
+
# testnet experience is byte-for-byte unchanged. This is DISPLAY ONLY (Telegram
|
|
35
|
+
# alerts, logs, MCP handshake) — it never touches data-file names, state keys,
|
|
36
|
+
# the PyPI package id, or the .mcp.json tool namespace, so it can't collide with
|
|
37
|
+
# the storage/logic layer.
|
|
38
|
+
_BRAND_MAINNET = "Ocean Agent"
|
|
39
|
+
_BRAND_TESTNET = "자율 개체"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def agent_name(default: str = _BRAND_TESTNET) -> str:
|
|
43
|
+
"""User-facing display name. 'Ocean Agent' on mainnet, otherwise `default`.
|
|
44
|
+
Driven by the same PACIFICA_BASE_URL as data_tag(), so name and data
|
|
45
|
+
namespace always agree (mainnet name ↔ mainnet files)."""
|
|
46
|
+
return _BRAND_MAINNET if data_tag() == "mainnet" else default
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# 네트워크 분리 이전(구버전)의 라이브 파일 이름들. 매트릭스는 공유라 제외.
|
|
50
|
+
_LIVE_FILES = ["autonomous.json", "equity.jsonl", "bot.log", "calibration.json",
|
|
51
|
+
"observations.jsonl", "signal_stats.json", "observe_rotation.txt",
|
|
52
|
+
"postmortem.jsonl", "bot_state.json", "predictions.json"]
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def migrate_brand_rename() -> list:
|
|
56
|
+
"""옛 이름(~/.mustache_*)의 데이터를 새 이름(~/.ocean_agent_*)으로 1회 옮긴다.
|
|
57
|
+
|
|
58
|
+
0.3.0 에서 배포 이름이 mustache-mcp → ocean-agent 로 바뀌면서 홈 데이터
|
|
59
|
+
파일 접두어도 함께 바뀌었다. 이사가 없으면 기존 사용자는 쌓아온 매트릭스·
|
|
60
|
+
관측·손익 기록을 통째로 잃고 빈 상태로 다시 시작하게 된다.
|
|
61
|
+
|
|
62
|
+
안전 규칙 두 가지:
|
|
63
|
+
· 새 이름이 이미 있으면 건드리지 않는다 (멱등 — 여러 번 불러도 안전)
|
|
64
|
+
· 복사가 아니라 이름 변경이라 디스크를 두 배로 쓰지 않는다
|
|
65
|
+
(bincache 는 378MB 라 복사하면 느리고, 어차피 재다운로드 가능하다)
|
|
66
|
+
"""
|
|
67
|
+
home = os.path.expanduser("~")
|
|
68
|
+
moved = []
|
|
69
|
+
try:
|
|
70
|
+
entries = os.listdir(home)
|
|
71
|
+
except OSError:
|
|
72
|
+
return moved
|
|
73
|
+
for entry in entries:
|
|
74
|
+
if not entry.startswith(".mustache_"):
|
|
75
|
+
continue
|
|
76
|
+
old = os.path.join(home, entry)
|
|
77
|
+
new = os.path.join(home, ".ocean_agent_" + entry[len(".mustache_"):])
|
|
78
|
+
if os.path.exists(new):
|
|
79
|
+
continue # 이미 옮겨졌거나 새로 만들어진 것
|
|
80
|
+
try:
|
|
81
|
+
os.rename(old, new) # 파일·디렉터리 모두 처리
|
|
82
|
+
moved.append(entry)
|
|
83
|
+
except OSError:
|
|
84
|
+
pass # 사용 중이면 다음 실행에 다시 시도
|
|
85
|
+
return moved
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def migrate_legacy_data() -> list:
|
|
89
|
+
"""구버전 untagged 라이브 파일(~/.ocean_agent_X)을 testnet 태그본으로 1회 이전한다.
|
|
90
|
+
|
|
91
|
+
지금까지 봇은 테스트넷에서만 돌았으므로 기존 데이터는 전부 테스트넷 것이다 →
|
|
92
|
+
항상 'testnet' 태그로만 옮긴다(현재 네트워크가 메인넷이어도 옛 테스트넷 데이터를
|
|
93
|
+
메인넷에 섞지 않기 위해). 태그본이 이미 있으면 건드리지 않아 멱등하며,
|
|
94
|
+
.bak/.polluted 등 접미사 백업은 정확한 이름이 아니라 옮기지 않는다."""
|
|
95
|
+
home = os.path.expanduser("~")
|
|
96
|
+
moved = []
|
|
97
|
+
for name in _LIVE_FILES:
|
|
98
|
+
legacy = os.path.join(home, f".ocean_agent_{name}")
|
|
99
|
+
tagged = os.path.join(home, f".ocean_agent_testnet_{name}")
|
|
100
|
+
if os.path.exists(legacy) and not os.path.exists(tagged):
|
|
101
|
+
try:
|
|
102
|
+
os.replace(legacy, tagged)
|
|
103
|
+
moved.append(name)
|
|
104
|
+
except OSError:
|
|
105
|
+
pass
|
|
106
|
+
return moved
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def api_key_from_env(base_url: str = "") -> str:
|
|
110
|
+
"""네트워크에 맞는 API 키를 고른다.
|
|
111
|
+
|
|
112
|
+
에이전트 키는 메인넷·테스트넷에서 각각 따로 승인되므로 키가 다를 수 있다.
|
|
113
|
+
테스트넷 대상이고 PACIFICA_API_KEY_TESTNET 이 있으면 그것을, 아니면
|
|
114
|
+
PACIFICA_API_KEY (구 AGENT_PRIVATE_KEY 호환)를 사용한다.
|
|
115
|
+
"""
|
|
116
|
+
if _is_testnet(base_url):
|
|
117
|
+
tn = os.environ.get("PACIFICA_API_KEY_TESTNET")
|
|
118
|
+
if tn:
|
|
119
|
+
return tn
|
|
120
|
+
return os.environ.get("PACIFICA_API_KEY") or os.environ.get("AGENT_PRIVATE_KEY", "")
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def address_from_env(base_url: str = "") -> str:
|
|
124
|
+
"""네트워크에 맞는 계정 주소를 고른다.
|
|
125
|
+
|
|
126
|
+
테스트넷은 별도 지갑을 쓸 수 있으므로 ADDRESS_TESTNET 을 우선 사용한다.
|
|
127
|
+
없으면 ADDRESS 로 폴백 (양쪽 같은 지갑을 쓰는 경우).
|
|
128
|
+
"""
|
|
129
|
+
if _is_testnet(base_url):
|
|
130
|
+
tn = os.environ.get("ADDRESS_TESTNET")
|
|
131
|
+
if tn:
|
|
132
|
+
return tn
|
|
133
|
+
return os.environ.get("ADDRESS", "")
|