Privora 泊睿 User Guide
Your cloud-native data workstation and quantitative monitoring powerhouse. Build automated data pipelines or run quantitative strategies with built-in A/H stock data — no tedious low-level coding required.
Getting Started
- Registration & Survey: After your first registration and login, the system will guide you through a Welcome Survey (role, purpose, etc.). Once completed, a Product Tour will automatically play, walking you through each sidebar module to help you quickly familiarize with the layout.
- Re-trigger Tour: If you skipped the tour, you can restart it anytime by clicking "Feature Tour" at the bottom of the left navigation bar.
- Language Switch: Click "Language" in the sidebar to switch the system language in real-time.
AI Assistant
1. Entry Point
- Once logged in, an "AI Assistant" entry appears near the bottom of the sidebar (next to the language switcher); click it to open the chat drawer. It is text-first today — no microphone needed. This entry only appears once an admin has enabled the feature for your environment.
2. What It Can Do
- Ask it in plain language how to use the platform, or to look up data on a dashboard/asset; you can also ask "what can you do" and it will list the operations currently available to you.
3. Voice-Dictated Bookkeeping
- You can dictate a real-money position trade (buy/sell) covering stocks, gold, or off-exchange funds (say the 6-digit fund code); key details like the account and amount are echoed back on a confirmation card first, and the trade is only recorded after you confirm.
4. Portfolio Summary Card
- Ask something like "how's my portfolio doing" and it returns a summary card with total market value and floating P&L at a glance.
Home Overview
1. Six Stat Cards
- Total portfolio value, today's P&L, subscription count, token count, API calls in the last 7 days, and scheduled-job total/active counts — any card with no data shows a matching call-to-action (e.g. "Create a Token") instead of a bare zero.
2. New-User Guidance
- A newly registered account with no positions or subscriptions yet sees 2 scenario cards pointing to common entry points, plus a 7-step checklist: create a token → subscribe to a data asset → complete your first API call → configure an alert rule → connect a webhook (Feishu/WeChat) → run a backtest → connect an agent. Progress shows up in the welcome line and progress bar.
3. Active-User Operations Panel
- Once the checklist is fully complete, this area switches to Quick Actions plus a 3-column band (job health over the last 24 hours, today's alerts) for daily monitoring — the new-user checklist no longer shows.
Insight Studio (Dashboards)
1. Build Dashboards & Global Variables
- Data Binding: Bindtime-series charts and tables directly to registered assets from the Asset Catalog, or select "Custom SQL Query" to write raw SQL.
- Linked Filtering: Add global dropdown variables (e.g. stock_code), reference them in chart SQL via ${stock_code}. Switch the dropdown and all charts refresh instantly.
2. Metric Alerts
- Click "New Alert" and pick a scenario (search a built-in instrument for A-shares / HK / Funds / Gold, or choose "Custom metric" to bind any subscribed data asset + column filters) to define what's being watched.
- Set the trigger condition (e.g. "when the latest value of Close Price is less than 1500, notify me"), then pick a configured Webhook datasource as the channel under "How to notify" — add a WEBHOOK-type datasource under Asset Studio -> Data Source Connections first if you don't have one yet.
- Under "Advanced", set the silence period (minutes, default 60) and the daily fire cap to keep one rule from repeatedly flooding you with notifications.
Asset Studio (Data Foundation)
1. Configure Data Source Connections
- Category: Select system type — Database, API, Webhook (for alert notifications like Feishu/DingTalk bots), etc.
- Authentication: Fill in credentials for databases; configure Token or Sign Secret for API/Webhook.
- Server Type: Choose Production, Development, or Test to achieve physical multi-environment isolation.
- Hologres (Alibaba Cloud's real-time data warehouse) was added as a data source type.
2. Register & Manage Data Assets
- Sensitivity Control: Public — visible to other teams. Internal — private to your team.
- Data Profile: In the detail page, click "Data Profile" to auto-generate null rates, min/max values, and distribution charts for each column.
3. New Data Asset Families
- The marketplace catalog gained two new directly-subscribable datasets: off-exchange/on-exchange fund daily prices and NAV (fund_day, ~15 years of history) and fund dividends (fund_dividend); usage matches the existing equity-price assets — search and subscribe from the Marketplace.
Process Studio (Data Factory)
1. Process Diagram Canvas
- Drag & Configure Nodes: Drag Database, API, Transform, Filter nodes from the left panel onto the grid. Double-click to configure. For SQL nodes, write logic and click "Format SQL" to beautify. Supports Retry Times on failure.
- Connection Control: Drag from a node's right port to the next node. Double-click a line to set trigger conditions (On Success for normal flow, On Failure for fallback compensation).
- Version Snapshots: The system auto-saves snapshots of every modification. Supports version diff "Compare" and one-click "Restore" rollback.
- Agent / API Updates: Agents and scripts can update an existing pipeline via PUT /api/ingestions/{id} (scope process.pipeline.update). Omit nodes to rename only; send nodes=[...] to fully replace steps. Every PUT writes a version snapshot — any mistake can be rolled back from the Versions tab. Legacy rows with an empty team are rejected with 403 until backfilled.
2. Built-in Components
The left panel of the diagram editor provides various components. Drag them onto the canvas and double-click to configure. Each component has a "Guide" tab with detailed usage instructions.
Python Script (python_script)
Run custom Python code with the built-in lg_utils library (no installation required):
get_context()— View your team's available assets, datasources, dashboards, and processesget_asset_data("name", filter_column=..., filter_value=[...], filter_operator="eq")— Fetch asset data. Pass a list to filter_value + filter_operator="eq" to do a single IN query across many symbols (e.g. stock_num IN (601985,600050,002085))get_portfolio_positions(stock_num=None)— Read your team's current holdings; each row carries the latest Process recommendation (Action / Add1,2 / Reduce1,2)get_trading_records(account_id=None, market=None, stock_num=None, trade_type=None, page=1, size=50)— Read your team's trading records, paginated. Filter optionally by accountId, market, stockNum, tradeType. Use for swing-monitor anchors (latest BUY/SELL) or transaction-record-driven backtests inside Process.write_recommendations([{...}])— Append per-stock recommendation rows (history is preserved). The holdings page exposes the history via a per-row "Rec history" button — paginated, newest first.get_connection("ds_name")— Connect to team datasources (auto-resolves config; supports PostgreSQL/MySQL/Oracle/SQL Server)get_variable("key")— Read scheduling context variables (job name, batch number, etc.)put_variable("key", value)— Write a variable back into the pipeline context so downstream steps can reference it via ${key} (good for log summaries, counts, small JSON values; ≤ 64 KB per value)log.info() / warn() / error()— Structured log output, displayed in real-time in execution logsbacktest(..., persist=True, persist_name="...")— Run a historical backtest and persist the result to My Backtests in one call; multiple runs with different persist_name values can be compared side-by-side on Sharpe, max drawdown, and total return.result.persist(name="...")— Manually persist an existing backtest result to My Backtests — useful for recording a result outside of a backtest() call, or backfilling.
SQL Execution (sql)
Execute SQL statements on a specified datasource. Supports multiple statements separated by semicolons, variable substitution ${variable}, and row_count tracking.
Fetch Asset Data (fetchAssetData)
Pull paginated rows for a registered asset into a pipeline variable — downstream Python / SQL / Loop nodes read via ${varName.data}. Supports single- and multi-value filters (e.g. stock_num="601985,600050" → IN query). Team permissions are enforced automatically; no credentials are exposed to the step.
Fetch Team Holdings (fetchPortfolioPositions)
Load your team's current portfolio into a pipeline variable, each row enriched with the latest Process recommendation. Typical pattern: fetchPortfolioPositions → pythonScript that scores each holding → write_recommendations() to push the result back to the holdings page.
Conditional Branch (if)
Route the flow to different branches based on condition expressions. Supports comparison operators (>, <, ==), logical operators (&&, ||), and an else default branch.
Loop (for)
Loop over child steps. Three modes: counter loop (i=0;i<10;i++), SQL cursor loop (row in SELECT ...#datasource), file line loop (line open path).
Variable Assignment (var)
Set or compute variable values. Supports strings, numbers, JSON, SQL query results, and math expressions. Enable setGlobal to write variables to the global context.
HTTP Call (callService)
Call external REST APIs. Supports GET/POST/PUT/DELETE with custom headers. Response available via ${logInfo} in subsequent steps.
Send Email (sendMail)
Send email notifications via SMTP. Supports HTML/plain text, multiple recipients/CC, and variable substitution. Ideal for completion notifications and alerts.
3. Team-Shared Python Methods
- Turn functions/classes your team reuses often into a shared module, then call it from any python_script step with
from team_lib.<module_name> import .... Saving runs a security scan that blocks high-risk calls likeos.system/subprocess/eval; inside the module you can useget_variable/put_variabledirectly, sharing the same process-context variables as python_script steps.
3.5 Process Runtime — Backtest API
1. Quick Start (3 steps)
- In the Process List, create a new process.
- Drag in a
python_scriptnode and write your strategy (see the example below). - Run the process; results are saved to My Backtests.
2. Minimal Single-Stock Example (stock_day)
Uses the stock_day asset (built-in A/H share daily bars). Column mapping: date_column="day_id", price_columns={open: "OPEN_PRICE", close: "CLOSE_PRICE"}, filter_column="STOCK_NUM".
from lg_utils import get_variable
from lg_utils.backtest_examples.stock_day import run_stock_day_backtest
def my_strategy(bar, ctx):
if len(ctx.history) < 20:
return
ma20 = sum(b.close for b in ctx.history[-20:]) / 20
if bar.close > ma20 and ctx.position == 0:
ctx.buy(size="all")
elif bar.close < ma20 and ctx.position > 0:
ctx.sell(size="all")
result = run_stock_day_backtest(
strategy=my_strategy,
stock_num=get_variable("stock_num", "000001"),
start=get_variable("start_date"), # 'YYYYMMDD' or 'YYYY-MM-DD'
end=get_variable("end_date"),
initial_cash=1_000_000,
commission_bps=3,
slippage_bps=1,
)
print(result.summary())
result.export_to_context("run1") # snapshot to run log
result.persist(name="run1") # save to My Backtests
3. Full backtest() Signature (24 parameters)
All parameters with defaults — pass only what differs from the defaults:
strategy— Callablefn(bar, ctx), or an object withon_bar(bar, ctx). Optional hooks:on_start(ctx)/on_end(ctx).asset— Asset ID (int) or asset name (str) — passed toget_asset_data.start, end— Date strings (closed interval) used to slice bars.None= no clipping. Both 'YYYYMMDD' and 'YYYY-MM-DD' are auto-normalized.initial_cash— Starting cash. Default:1_000_000.0.commission_bps— Commission in basis points (1 bp = 1/10 000). Default:0.0.slippage_bps— Slippage in basis points. Default:0.0.fill—"next_open"(default) — fills at the open of the next bar."this_close"— fills at the current bar's close.date_column— Column name that holds the bar date. Default:"trade_date". For stock_day use"day_id".price_columns— Dict mapping logical names to actual column names, e.g.{"open": "OPEN_PRICE", "close": "CLOSE_PRICE"}. Defaults: open/high/low/close/volume.filter_column, filter_value— Server-side filter pushed toget_asset_data. Use for multi-symbol tables (e.g.filter_column="STOCK_NUM", filter_value="000001").warmup_bars— First N bars are fed toctx.historybut the strategy callback is not called. Default:0.max_bars— Hard cap on bars loaded to avoid runaway fetches. Default:1_000_000.max_history— Max length ofctx.history.None= unlimited.on_trade— Callbackfn(trade_dict)fired on each completed round-trip.benchmark_asset— Optional asset name/ID for benchmark comparison. Producesbenchmark_return,alpha,betain metrics.benchmark_price_column— Benchmark close column. Defaults to the same asprice_columns["close"].benchmark_filter_column, benchmark_filter_value— Server-side filter for the benchmark asset (same semantics as filter_column / filter_value).persist— IfTrue, callsresult.persist(name=persist_name)automatically at the end. Default:False.persist_name— Label stored whenpersist=True; same as thenamearg ofBacktestResult.persist().bars— Bypassget_asset_dataand supply bars directly as a list of dicts (useful for unit tests or custom data sources).
4. Runtime Objects: Bar / Context / BacktestResult
Bar — Named-tuple passed to the strategy callback each tick.
bar.dt— Bar date string (same value as the rawdate_columnfield).bar.open, bar.high, bar.low, bar.close, bar.volume— Resolved numeric prices and volume.Noneif the column is absent in the asset.bar.raw— Original raw row dict from the data source — useful for accessing non-price columns.
Context — Strategy runtime context — holds account state and order submission methods.
ctx.position— Current number of shares held (integer, long-only).ctx.cash— Available cash.ctx.equity— Total portfolio value: cash + position × current bar close.ctx.nav— Net asset value relative to initial cash (equity / initial_cash).ctx.history— List of allBarobjects seen so far (capped atmax_history).ctx.buy(size="all", limit_price=None)—size:"all"(use all available cash), float ∈ (0,1] (fraction of cash), or positive int (share count).limit_priceacts as a cap — order skipped if fill price exceeds it.ctx.sell(size="all", limit_price=None)—size:"all"(sell full position), float ∈ (0,1] (fraction of position), or positive int.limit_priceacts as a floor.ctx.close_all()— Convenience: sell full position if any is held.ctx.order_target_pct(pct)— Adjust holding topct × equityworth of shares.pct ∈ [0, 1].
BacktestResult — Returned by backtest(). Contains all outcome data.
result.metrics— Dict with total_return, cagr, sharpe, sortino, max_drawdown, win_rate, profit_factor, num_trades, exposure, and (if benchmark provided) benchmark_return, alpha, beta.result.trades— List of round-trip trade dicts: entry_dt, exit_dt, qty, entry_px, exit_px, pnl, return_bps.result.equity_curve— List of per-bar account snapshots (see §7 for schema).result.summary()— Returns a formatted multi-line string of all key metrics — useful for print() in the run log.result.export_to_context(name)— Writes a sentinel line to stdout so PythonScriptStep captures it in the job log.result.persist(name=...)— Persists the result to theprocess_backtest_resulttable (append-only, team-isolated). Requires running inside PythonScriptStep.
5. Portfolio Backtest (backtest_portfolio)
Runs multiple assets against a shared cash pool. Use run_stock_day_portfolio_backtest for the built-in stock_day asset. result.metrics["per_asset"] contains per-symbol return, max_drawdown, num_trades, and contribution. The assets / stock_nums list order determines which strategy gets to fill first when multiple size='all' orders land on the same bar.
from lg_utils.backtest_examples.stock_day import run_stock_day_portfolio_backtest
def make_ma_strategy(fast, slow):
def strategy(bar, ctx):
if len(ctx.history) < slow:
return
ma_fast = sum(b.close for b in ctx.history[-fast:]) / fast
ma_slow = sum(b.close for b in ctx.history[-slow:]) / slow
if ma_fast > ma_slow and ctx.position == 0:
ctx.buy(size=0.5) # use 50% of available cash
elif ma_fast < ma_slow and ctx.position > 0:
ctx.sell(size="all")
return strategy
result = run_stock_day_portfolio_backtest(
strategies={
"000001": make_ma_strategy(5, 20),
"600519": make_ma_strategy(10, 30),
},
stock_nums=["000001", "600519"], # settlement order for size='all'
start="20240101", end="20241231",
initial_cash=1_000_000,
commission_bps=3,
)
print(result.summary())
# result.metrics["per_asset"] has per-stock contribution / max_dd
result.persist(name="portfolio-v1")
6. Transaction-Record-Driven Backtest
Use get_trading_records() to read real BUY/SELL anchors from your trading history, then replay those entry dates in the backtest engine to measure what the outcome would have been.
import datetime
from lg_utils import get_trading_records
from lg_utils.backtest_examples.stock_day import run_stock_day_backtest
# Load actual BUY anchors from trading history
# Response shape: {"success": True, "data": [...], "totalElements": N, ...}
# Field names use Jackson camelCase: tradeDate, stockNum, price, tradeType
records = get_trading_records(stock_num="000001", trade_type="BUY", size=1)
if records.get("totalElements", 0) == 0:
print("No BUY records found.")
else:
latest_buy = records["data"][0]
last_buy_date = str(latest_buy["tradeDate"])[:10] # e.g. '2024-01-15'
buy_price = float(latest_buy["price"])
upper = buy_price * 1.10
lower = buy_price * 0.90
def swing_strategy(bar, ctx):
if bar.close is None:
return
if ctx.position == 0 and bar.close <= lower:
ctx.buy(size="all")
elif ctx.position > 0 and bar.close >= upper:
ctx.sell(size="all")
end_date = datetime.date.today().strftime("%Y-%m-%d")
result = run_stock_day_backtest(
strategy=swing_strategy,
stock_num="000001",
start=last_buy_date,
end=end_date,
initial_cash=500_000,
)
result.persist(name="replay-from-records")
7. equity_curve JSON Schema
Each element in result.equity_curve corresponds to one bar:
// equity_curve: list of objects, one per bar
[
{
"dt": "20240101", // bar date (string, same format as date_column)
"equity": 1_000_000.0, // total portfolio value (cash + position mark)
"cash": 800_000.0, // available cash
"position": 100, // shares held (int; portfolio mode: count of non-zero positions)
"close": 55.80 // bar close price (portfolio mode: weighted mark equity)
},
...
]
The UI at My Backtests renders this curve as a line chart (equity over time) and uses equity to compute drawdown. The cash and position fields are shown in the detail panel.
8. The __LG_BACKTEST_RESULT__ Sentinel
Two ways to surface results after a run:
// Emitted by result.export_to_context("name") — appears in the run log:
__LG_BACKTEST_RESULT__:<name>:<json-payload>
// Emitted by result.persist(...) — writes to process_backtest_result table:
// Returns the new row id. Visible at /profile/backtest-results.
9. Where Results Appear After Execution
Results saved with result.persist() or backtest(..., persist=True) are visible at Profile → My Backtests. The panel shows a sortable table of all your named runs with key metrics; click any row to open the equity-curve chart and trade log.
10. CLI Parameter Injection (get_variable)
The backend passes scheduling variables to the script as command-line flags. Both --start_date and -start_date are equivalent — the runtime strips all leading dashes before exposing the value via get_variable("start_date").
# Both forms are equivalent — the runtime strips leading dashes:
# --start_date 2024-01-01
# -start_date 2024-01-01
# Both surface as:
from lg_utils import get_variable
start = get_variable("start_date") # => "2024-01-01"
Schedule Studio (Automation Engine)
1. Configure Scheduled Jobs
- Bind the Process or script to execute. Use the built-in "Cron Expression Builder" to quickly generate timing strategies (e.g. daily at 2 AM). Configure Dependencies to ensure downstream triggers only after upstream success.
2. Instance Monitoring & Intervention
- Turn on "Auto Refresh: ON" in the top-right corner to use as a real-time monitoring dashboard — track Pending/Running/Success/Failed status live.
- Manual Intervention: View Logs (pull real execution logs), Kill (force-kill stuck tasks), Redo Job (one-click re-run after fixing logic), View Lineage (3-level dependency graph).
3. Dependency Groups: OR Within a Group, AND Across Groups
- Give several dependencies the same Group name and any one of them satisfies the group (OR); different groups still all have to be satisfied for the job to trigger (AND). Dependencies with no Group are independent, matching the previous "all AND" behavior unchanged.
4. Remote Execution: Machine Pools + Dispatch Policy
- Selecting "Remote machine (SSH)" as the execution mode lets you pick multiple machines from your existing data source connections into a pool, with a priority per machine. Dispatch policy supports Round Robin, Failover, or Random, determining which machine actually runs each invocation.
Wealth Studio
accountType=all now default to "Real".Paper Trading
Marketplace & API Consumption
1. Marketplace
- Browse all published data assets and dashboards across the platform. Click "Subscribe" to add them to your available permission pool. A newly published or edited item first goes through admin review — it shows as "Under review" and stays invisible/unsubscribable to others until approved. If an admin force-unpublishes an item, existing subscribers' access is revoked at the same time.
2. Token Management
- Key Scenario: Configure the generated Token directly in the official OpenClaw Agent plugin, or pass it to your own Python script, enabling fully automated data retrieval without login.
- Security: Fine-grained permission control (Scopes). Token is shown in plaintext only once at creation. If leaked, immediately click "Revoke" to block access.
- Scope Selection: A newly created token already comes with a set of scopes that can fetch data right away (asset list/detail/data reads, etc.) — no need to guess which boxes to check. The picker groups scopes by the real HTTP method of each endpoint, and offers a few scenario-based presets for one-click selection.
3. Preview Without Logging In
- You can open the Marketplace and browse published data assets and dashboards without logging in (it defaults to the "Data Assets" tab). Clicking a write action like "Get API / Subscribe" is intercepted and redirected to the login page — log in and retry to complete it.
4. Credits (Shadow Mode)
- Profile Settings gained a "Credit Usage" card, and some dataset listings in the marketplace show a rate badge (e.g. "N rows / credit"); publishers can set a rate for their own dataset listings. This is currently shadow mode — it only displays estimated usage and does not actually charge or throttle anything.
LLM & Intelligent Plugins (Agent Skills)
- Official ClawHub skill package — install into Claude, OpenClaw or any ClawHub-compatible client and call it in natural language; see "Official Plugin Support" below.
- MCP Server (stdio) — for native MCP clients such as Claude Code, Cursor, Windsurf, Cline, and Codex CLI; see "MCP Server" below.
- Bearer Token + HTTP API — call the REST endpoints directly from your own script, the most flexible option; see "Bearer Token + HTTP API" below.
- Anonymous read-only — run read-only queries with no sign-up, rate-limited; see "Anonymous read-only" below.
/agent-guide 是面向未登录访客的完整版接入指南(含安装命令与新手常见坑),本节是登录后的操作细节。
1. 3-step quick start
- Create a Bearer token at /profile/tokens, selecting the scopes you need
- Set environment variables
LG_AGENT_TOKEN=<your-token>andLG_AGENT_BASE_URL=https://privora.cn - Call
GET /agent/skillsto list available skills, thenPOST /agent/skills/executeto run one
dataasset.metadata.get. If you also need to subscribe to marketplace items (to obtain a clonedAssetId), tick the "Read data & manage marketplace subscriptions" preset when creating the token (it adds marketplace.item.subscribe) — the default preset does not include it. paper.* (paper-trading execution) is reserved for internal platform use and auto-issued when you bind a strategy; those checkboxes never appear on the create page, so there is nothing to look for.
2. Bearer Token + HTTP API
GET /agent/skills (list available skills) POST /agent/skills/execute (execute a skill) GET /api/public/agent/token-introspect (connectivity smoke test)
See the full skill catalog at the skill manifest (risk tier, required fields, and gotchas for every skill).
confirmRequired=true returns 409 — see that operation's metadata in the skill manifest. For example, schedule.job.delete (🔴) and schedule.instance.kill (🔴) both return 409 in token mode. The approval flow is only supported in session mode.
3. Official Plugin Support:
- Run clawhub install privora-cn-quant in OpenClaw Hub / ClawHub to install the full official plugin (data, pipelines, backtesting, paper trading); if you only need real-time alerting, install the smaller clawhub install privora-alert instead. You can also search "Privora" in the Coze/GPT Store.
4. MCP Server (stdio)
Wraps GET /agent/skills / POST /agent/skills/execute as native MCP tools, for stdio MCP clients such as Claude Code, Cursor, Windsurf, Cline, and Codex CLI.
npm install -g https://privora.cn/downloads/privora-mcp-server-0.1.1.tgz
curl -fsSLO https://privora.cn/downloads/privora-mcp-server-0.1.1.tgz
curl -fsSLO https://privora.cn/downloads/privora-mcp-server-0.1.1.tgz.sha256
sha256sum -c privora-mcp-server-0.1.1.tgz.sha256
{
"mcpServers": {
"lg-agent": {
"command": "lg-agent-mcp-server",
"env": {
"LG_AGENT_BASE_URL": "https://privora.cn",
"LG_AGENT_TOKEN": "lgatk_your_token_here"
}
}
}
}
- Claude Code — project scope writes
.mcp.json(shared via version control); user and local scope live in~/.claude.json. Or just use theclaude mcp addcommand below. (official docs) - Cursor —
~/.cursor/mcp.jsonglobally,.cursor/mcp.jsonper project. (official docs) - Windsurf —
~/.codeium/windsurf/mcp_config.json. (official docs) - Cline —
~/.cline/mcp.jsonfor the CLI; for the IDE extension use the UI: MCP Servers in the top toolbar → Configure → Configure MCP Servers. (official docs) - Codex CLI —
~/.codex/config.toml(or.codex/config.tomlper project). It is TOML, not the JSON above — see below. (official docs) - The first four all take the same
mcpServersJSON shape, so the block above pastes in as-is; only thelg-agentname is yours to choose.
claude mcp add --env LG_AGENT_BASE_URL=https://privora.cn --env LG_AGENT_TOKEN=lgatk_your_token_here --transport stdio lg-agent -- lg-agent-mcp-server
codex mcp add lg-agent --env LG_AGENT_BASE_URL=https://privora.cn --env LG_AGENT_TOKEN=lgatk_your_token_here -- lg-agent-mcp-server
mcpServers JSON above into ~/.codex/config.toml will fail to parse — use the block below instead. Also, Claude Code's --env must not be immediately followed by the server name, or the name is read as another KEY=VALUE and rejected — that is why the command above puts --transport stdio in between.
[mcp_servers.lg-agent]
command = "lg-agent-mcp-server"
[mcp_servers.lg-agent.env]
LG_AGENT_BASE_URL = "https://privora.cn"
LG_AGENT_TOKEN = "lgatk_your_token_here"
LG_AGENT_BASE_URL defaults to http://localhost:3000 — a website install MUST set it explicitly to https://privora.cn, or every call fails to connect. LG_AGENT_TOKEN is optional; omit it to run in anonymous mode.
Always 11 tools: 4 protocol-level meta-tools (list_skills / describe_skill / execute_skill / whoami) plus 7 first-class tools (dataasset_list, dataasset_get, dataasset_schema_get, dataasset_metadata_get, dataasset_data_get, dataasset_data_get_realtime, marketplace_item_list). All 11 always appear regardless of token; what actually succeeds depends on your token's scopes.
5. Anonymous read-only
- Works with no
LG_AGENT_TOKENand no login: a fixed set of 10 read-only skills (asset listing, schema, marketplace items, etc.) is always allowed, rate-limited per IP across three buckets. Good for a first try before deciding whether to register.
6. Natural Language Interaction: / Zero-Friction Feedback:
- Natural Language Interaction: After configuring the Token above, type commands directly in the chat: "Look up the latest data for asset ID 21" or "Monitor China Nuclear Power, notify me immediately if it drops below 9.5 yuan."
- Zero-Friction Feedback: Found a bug? No need to hunt for support. Just tell the Agent "This feature has an error, please submit feedback" — the AI will auto-capture context and push it directly to our backend management system.
- Subscribing to a marketplace item gives your own team a new, cloned asset id — not the publisher's id shown on the marketplace page. Re-resolve the id from the
marketplace.item.subscribe(ordataasset.list) response every time; never carry one over from a screenshot or chat log. - If you call
dataasset.data.getwith afilter_valuebut omitfilter_op, the default is a substring match (LIKE '%v%'), not exact — passfilter_op=eqexplicitly for an exact match. - The
{id}in URL paths must be the numeric asset ID; passing an asset name returns a 500 with an unhelpful message. - Do not manually add an
X-Agent-Modeheader — the Node proxy layer injects it automatically based on your Bearer token, and adding it yourself can get the request rejected. - Discover available skills via
GET /agent/skills, not/api/public/agent/capabilities— the latter is a trimmed view that omits the entire paper-trading surface. - On Windows Git Bash,
curl -d 'non-ascii text'silently mangles non-ASCII bytes — use--data-binary @fileinstead.
Admin Studio (Admin Only)
1. Component Permissions
- Control which component types each team can use in the diagram editor. Enter a team name and check the components that team is allowed to use.
- Unconfigured teams have access to all components by default.
- After selecting specific components and saving, the team's diagram editor will only show the authorized components.
- Selecting all components and saving removes restrictions, restoring full access.
Customer Use Cases — Real Workflows You Can Run
1. Discretionary → Quant Workflow (MACD Bucket Win-Rate)
Turn your real trading history into a quantifiable edge analysis. Upload your broker CSV, compute MACD slope at each entry, group trades into buckets, and find your highest-win-rate range. 4 steps.
-
Upload your broker CSV
Wealth Studio → Trading Records → click the "Import CSV" button (top-right of the page, next to "Add Trade")
Required CSV columns (header row mandatory):
trade_date,symbol,side,quantity,price 2024-03-15,600519,BUY,100,1700.50 2024-04-02,600519,SELL,100,1820.00External AI agent alternative: create a Bearer token at /profile/tokens, then POST /api/wealth/trading-records/import-csv with multipart/form-data and the token in the Authorization header.
-
Run the MACD-slope backtest pipeline
/diagram → New Process → add a Python Script step → paste the quickstart snippet
from lg_utils.backtest_examples.discretionary_macd_winrate import run run(persist_result=True)Defaults: MACD(12, 26, 9), 5-bar slope window, bucket width 0.1, 60 prior closes per trade. To customize: copy the full discretionary_macd_winrate.py script into your Process and edit the module-level constants. Or compose your own with lg_utils.indicators (sma / ema / macd / rsi / slope).
-
Add the Bucket Win-rate widget to a dashboard
/dashboards → choose or create a dashboard → Add Widget → Template dropdown → select "Bucket Win-rate (Discretionary → Quant)"
The template auto-generates a Custom-SQL skeleton over process_backtest_result. You only need to replace three placeholders: <run_name> (the label you passed to result.persist(name=...), default "discretionary_macd_winrate") / <indicator_col> (the JSON key your script attached to each trade, default "macd_slope") / <bucket_width> (e.g. 0.1). Save → the table renders win-rate per bucket.
Sample output:
bucket_low | n_trades | n_wins | win_rate_pct | avg_pnl -0.3 | 5 | 2 | 40.00 | -120.50 -0.2 | 8 | 4 | 50.00 | 30.20 -0.1 | 12 | 8 | 66.67 | 215.40 0.0 | 15 | 11 | 73.33 | 380.10 <-- best 0.1 | 10 | 6 | 60.00 | 180.50 0.2 | 6 | 3 | 50.00 | 50.30 0.3 | 3 | 1 | 33.33 | -250.10 -
(Optional) Ask an external AI agent in natural language
Tool layer (Privora) provides the data and computation; language layer (Coze / Qwen / Claude / OpenClaw) translates. Configure your Bearer token in the agent platform, then ask: "Which MACD-slope bucket has my highest win rate?" — the agent calls query_asset_data to read process_backtest_result and answers in natural language.