TL;DR
The Gemini CLI example buys 10 SPY shares on a 20-day average crossing above the 50-day average and sells the holding on a crossing below. Simply staying above the average does not trigger another entry. The validated preview has no paper results. Create a separate Paper book, verify its schedule and identity, then review orders and recorded forward history before pausing it.
Create and monitor a separate paper deployment
Preview the candidate
NexusTrade toolbuild_portfolio
Identity boundaryReview the canonical configuration and fix validation issues before saving
Author the candidate
NexusTrade toolcreate_portfolio
Identity boundaryA newly authored chat portfolio, not an existing live account
Inspect the target
NexusTrade toolget_portfolio
Identity boundaryRead the exact returned ID and strategies before activation
Deploy the chat book
NexusTrade toolupdate_portfolio
Identity boundaryoperations: [{type: "deploy", portfolioId: returnedChatId}] creates paper
Find the running book
NexusTrade toolfetch_portfolios
Identity boundaryKeep the resulting deployment ID separately from the original chat/draft ID
Read actual paper history
NexusTrade toolquery_portfolio_history
Identity boundaryThe deployed portfolio curve; never substitute a backtest curve
Show the table · 6 rows, 3 columns
Scroll sideways to compare all columns. Select a heading to sort.
| Preview the candidate | build_portfolio | Review the canonical configuration and fix validation issues before saving |
| Author the candidate | create_portfolio | A newly authored chat portfolio, not an existing live account |
| Inspect the target | get_portfolio | Read the exact returned ID and strategies before activation |
| Deploy the chat book | update_portfolio | operations: [{type: "deploy", portfolioId: returnedChatId}] creates paper |
| Find the running book | fetch_portfolios | Keep the resulting deployment ID separately from the original chat/draft ID |
| Read actual paper history | query_portfolio_history | The deployed portfolio curve; never substitute a backtest curve |
No matching rows. Clear the filter to see all records.
Deploying an existing live portfolio ID can reactivate real brokerage trading. For this workflow use the newly authored chat candidate and verify the returned deployment is paper. The SDK also separates saved draft IDs from deployment.portfolioId.
Validated example: SPY 20/50 crossover
- Starting capital
- $10,000
NexusTrade validation recorded October 10, 2026 returned valid:true with no issues. This preview saved nothing and has no forward Paper history.
Entry
Buy 10 shares of SPY whenever SPY's 20-day average price crosses above SPY's 50-day average price and the portfolio holds no SPY.
Exit
Sell 100% of the current SPY position whenever SPY's 20-day average price crosses below SPY's 50-day average price and the portfolio holds SPY.
Rule decision example
If the 20-day average has just crossed above the 50-day average and no SPY is held, the rule proposes buying 10 shares. Simply remaining above does not create another crossing.
Exit and equality
A confirmed crossing below with SPY held proposes selling the full holding. Without the required crossing, that rule does not pass.
Try this example in Gemini CLI
Inspect the request
Connect Gemini CLI, then copy the request below. Review the returned result before continuing.
Register remote MCP and authenticate in Gemini CLI
Run the shell commands below. --scope user makes the connection available across your CLI projects; use --scope project instead for this project only. This guide is for Gemini CLI, not the Gemini consumer chat app.
Start gemini in the folder where you will save the research files. Inside that session enter /mcp auth nexustrade, finish NexusTrade browser sign-in, then /mcp list. Use /mcp schema to inspect discovered input schemas. These slash commands belong in Gemini CLI, not your shell.
gemini mcp add --transport http --scope user nexustrade https://nexustrade.io/api/mcp
gemini mcp list
geminiConfirm access with an owned-resource read
Ask the client to discover tools and call fetch_portfolios, then pass one returned portfolioId as portfolio_id to get_portfolio. Inspect portfolioId, type, name, isActive and strategies; compare them with the same saved book in NexusTrade. Do not copy IDs from a demonstration. An empty list can be valid for a new account.
A tool-not-found error means revisit discovery. An authorization error means check the selected NexusTrade environment/account and OAuth connection. Do not ask the model to invent a replacement identifier.
Use only NexusTrade read tools. Call fetch_portfolios, then pass one returned portfolioId as the portfolio_id input to get_portfolio. Show portfolioId, type, name, isActive and complete strategies. Do not create, edit, backtest, deploy or place orders.Create a new candidate and observation record
Daily SPY crossover proposal: buy 10 shares only when the 20-day simple moving average crosses above the 50-day average and no SPY position is held; sell the entire SPY position when the 20-day average crosses below the 50-day average. Use the supported CrossAbove/CrossBelow event indicators, compared with 1, rather than treating every above-average day as a new cross.
Create paper/spy-cli-run-ledger.md with the draft ID, exact configuration, intended $10,000 simulated starting capital, activation date and a review date 30 calendar days later. Those are proposed observation inputs, not recorded performance. Historical testing should be reviewed separately before activation.
Ask Gemini CLI to call build_portfolio with the complete candidate. Inspect valid, canonical portfolio and each issue path, component and message. Fix issues and preview again. After valid is true and you have reviewed the rule, pass the same JSON to create_portfolio and read the saved draft with get_portfolio. Verify type=chat and isActive=false. Keep the generated JSON and returned ID in the record; a portfolio name containing paper does not establish deployment type.
Review the paper deployment operation
Show the actual update_portfolio operation before activation: operations contains a deploy entry whose portfolioId is the newly authored chat draft ID. Deploying a chat draft creates a separate paper book. An existing live ID can reactivate brokerage trading, so verify the draft type immediately before the call.
Preview a new candidate with build_portfolio using this rule: Daily SPY crossover proposal: buy 10 shares only when the 20-day simple moving average crosses above the 50-day average and no SPY position is held; sell the entire SPY position when the 20-day average crosses below the 50-day average. Use the supported CrossAbove/CrossBelow event indicators, compared with 1, rather than treating every above-average day as a new cross. Inspect valid, issues and canonical portfolio; fix issues and preview again. When valid and reviewed, pass the same JSON to create_portfolio. Save its full JSON and actual returned ID in paper/spy-cli-run-ledger.md. Use get_portfolio to verify type=chat and isActive=false. Show operations with type deploy and portfolioId equal to that chat ID. Wait for my approval. After activation, find the new deployment with fetch_portfolios and read it with get_portfolio. Stop if type is not paper. Do not deploy an existing live ID.Verify evaluation and review paper orders
Open the verified running paper portfolio in NexusTrade and inspect its Deployment Center. The Automated Trading switch controls strategy evaluation: if you choose to change it, select Save Changes and read the same portfolio again. Confirm isActive and record the actual deployment frequency. This control is separate from the live-only Autonomous Trading approval policy; paper portfolios remain on manual order review.
When a signal creates a pending simulated order, open Order Management, select Paper and Needs Review, and compare its portfolio, symbol, side and size with the frozen rules before choosing Confirm. Check the resulting order state and paper history. A pending approval is not a filled trade. An empty history can mean no qualifying signal or an unapproved order; it does not justify another deployment.
Verify the running identity and capital
After the approved deployment, use fetch_portfolios to find the new running book and get_portfolio on its returned ID. Confirm type=paper, isActive, strategies, initialValue and the returned deployment settings. Record the actual deployment frequency: Constant and OpenClose are evaluation schedules. A Day backtest interval or a day-based moving-average window does not set the paper evaluation cadence. Compare the capital and rules with the approved record before treating the experiment as started. Keep the chat draft ID and running portfolioId separately.
If several portfolios share a name, use returned IDs and the exact strategies rather than selecting by name alone. A transport timeout does not prove deployment failed. Read the account resources before attempting another deploy; duplicate deployments can create separate experiments.
Observe recorded paper history and recover
Read the explanation
If the server is missing, check whether you selected user or project scope. Use /mcp reload to rediscover tools after configuration changes. For expired tokens, repeat /mcp auth nexustrade. Shell gemini mcp list can show connection errors. After an interrupted terminal session, reopen the saved run ledger or /resume and continue with the recorded job or deployment ID.
Use query_portfolio_history with the verified running portfolio_id for the observation period. It returns recorded time/value points from the deployed book. get_portfolio_performance returns aggregates, while query_backtest_history reads historical simulations; neither replaces the deployed curve.
If history is empty, check type, activation time, active state and whether observations have been recorded. Do not backtest the same rules and label that curve paper performance. Record actual positions, activity and any rule/cash changes beside the curve.
At the review date compare behavior with the frozen plan. When the observation ends, review update_portfolio with operations containing type undeploy and portfolioId equal to the verified running paper ID. After the approved pause, call get_portfolio again and require type=paper and isActive=false. Keep the recorded history; pausing does not require deleting the book.
Pause the verified paper book
Replace the placeholder with the running paper ID you have just read with get_portfolio. Submit this operation only after reviewing that identity and approving the pause. Read the same ID afterward and require type=paper and isActive=false.
{
"operations": [
{
"type": "undeploy",
"portfolioId": "<verified-running-paper-id>"
}
]
}Costs and the next task
The local file and proposed rule are planning artifacts. Research and backtest submissions can consume credits; detailed backtest events increase cost. Check your plan and the proposed operation before submitting. Review the exact connected account before making changes.
For live deployment, review the separate broker guide, exact trading account and permissions. Choose the broker guide that matches your trading account.
Exact validation request and provenance
Inspect the complete paper-candidate JSON and validation provenance
On October 10, 2026, we constructed the complete SPY configuration below with the NexusTrade Python SDK and sent it to build_portfolio. The product returned valid: true, an empty issues list and the canonical rule descriptions in this table.
The entry uses CrossAbove of the 20-day and 50-day averages with a zero-position guard; the exit uses CrossBelow with a positive-position guard. The indicator result is compared with 1. These are crossing events, not a repeated above/below state check. Entry buys 10 shares; exit sells the full current holding.
Copy the full request into build_portfolio before saving it. The actual preview saved nothing, submitted no backtest and activated no paper book. Both returned rules have automaticOrderApproval: false. Use the client steps below to create and observe your own paper draft.
| Product response | Observed value |
|---|---|
| Validation | valid: true; issues: [] |
| Capital | initialValue: 10000 |
| Entry | Buy 10 shares of SPY whenever SPY's 20-day average price crosses above SPY's 50-day average price and the portfolio holds no SPY. |
| Exit | Sell 100% of the current SPY position whenever SPY's 20-day average price crosses below SPY's 50-day average price and the portfolio holds SPY. |
| Order approval | automaticOrderApproval: false on both returned rules |
| Persistence | Nothing was saved |
No matching rows. Clear the filter to see all records.
View complete record
{
"name": "Public SEO example - SPY 20/50 crossover",
"initialValue": 10000,
"cash": 10000,
"buyingPower": 10000,
"strategies": [
{
"name": "Buy on a fresh cross",
"condition": {
"type": "And",
"conditions": [
{
"type": "Base",
"lhs": {
"type": "CrossAbove",
"indicators": [
{
"type": "SimpleMovingAverage",
"targetAsset": {
"type": "Stock",
"symbol": "SPY",
"name": "SPY"
},
"window": {
"length": 20,
"interval": "Day"
}
},
{
"type": "SimpleMovingAverage",
"targetAsset": {
"type": "Stock",
"symbol": "SPY",
"name": "SPY"
},
"window": {
"length": 50,
"interval": "Day"
}
}
]
},
"comparison": "equal",
"rhs": {
"type": "Value",
"value": 1
}
},
{
"type": "Base",
"lhs": {
"type": "PositionValue",
"targetAssets": [
{
"type": "Stock",
"symbol": "SPY",
"name": "SPY"
}
]
},
"comparison": "equal",
"rhs": {
"type": "Value",
"value": 0
}
}
]
},
"action": {
"type": "Buy",
"targetAsset": {
"type": "Stock",
"symbol": "SPY",
"name": "SPY"
},
"amount": {
"type": "number of assets",
"amount": 10
}
},
"orderExecution": {
"type": "Market"
}
},
{
"name": "Sell on reverse cross",
"condition": {
"type": "And",
"conditions": [
{
"type": "Base",
"lhs": {
"type": "CrossBelow",
"indicators": [
{
"type": "SimpleMovingAverage",
"targetAsset": {
"type": "Stock",
"symbol": "SPY",
"name": "SPY"
},
"window": {
"length": 20,
"interval": "Day"
}
},
{
"type": "SimpleMovingAverage",
"targetAsset": {
"type": "Stock",
"symbol": "SPY",
"name": "SPY"
},
"window": {
"length": 50,
"interval": "Day"
}
}
]
},
"comparison": "equal",
"rhs": {
"type": "Value",
"value": 1
}
},
{
"type": "Base",
"lhs": {
"type": "PositionValue",
"targetAssets": [
{
"type": "Stock",
"symbol": "SPY",
"name": "SPY"
}
]
},
"comparison": "greaterThan",
"rhs": {
"type": "Value",
"value": 0
}
}
]
},
"action": {
"type": "Sell",
"targetAsset": {
"type": "Stock",
"symbol": "SPY",
"name": "SPY"
},
"amount": {
"type": "percent of current positions",
"amount": 100
}
},
"orderExecution": {
"type": "Market"
}
}
],
"supportsFractionalShares": false,
"supportsCrypto": false,
"alertsEnabled": false,
"dividendPolicy": "cash"
}
No comments yet.