1. Introduction: Insights from the AI Trading Arena
Recently, American AI lab nof1ai launched a compelling experiment—giving six top AI models (Claude, DeepSeek, Gemini, GPT-5, Grok, and Tongyi Qianwen) $10,000 each to compete in the real cryptocurrency perpetual futures market. This wasn't a simulation, but actual trading with real money. The results were surprising: China's DeepSeek consistently led the pack, while both GPT-5 and Gemini crashed and burned. The greatest value of this competition lies in the team's decision to open-source all the prompts, data structures, and decision-making processes they used, providing us with an excellent blueprint for studying AI quantitative trading.

This article will provide a detailed breakdown of every node and logic element in an AI quantitative trading workflow based on this publicly available architecture, helping you understand how AI makes trading decisions in real markets.
2. Overall Architecture: A Three-Stage Perception-Decision-Execution System
This AI quantitative trading system employs the classic "Perception-Decision-Execution" three-stage architecture, with the entire workflow composed of multiple core nodes:
- Timer Trigger - System heartbeat, triggered every 3 minutes
- Parameter Reset - Account status monitoring and performance statistics
- Market Data Acquisition - Multi-dimensional data retrieval and indicator calculation
- Position Data Acquisition - Current position status tracking
- Data Merging - Integration of account and market information
- AI Agent - Core decision-making engine
- Trade Execution - Signal parsing and order processing Let's dive deep into the design logic of each node one by one.
3. Node 1: Timer Trigger
Functional Positioning
The timer trigger is the initiator of the entire workflow, similar to the human heartbeat, periodically driving the system's operation.
Design Considerations:
3-minute cycle: Balances data freshness with API call limitations
Fixed intervals: Ensures stability and predictability of strategy execution
4. Node 2: Parameter Reset (Account Status Management)
Functional Positioning
This is a critical state management node responsible for initializing, tracking, and calculating various core account metrics.
Core Code Analysis
javascript
// Set Binance testnet API base URL
api_base = "https://testnet.binancefuture.com"
exchange.SetBase(api_base)
// Initialization check - set baseline values on first run
if (_G('invoketime') === null) {
_G('invoketime', 0);
_G('STARTTIME', Date.now());
const initAccount = exchange.GetAccount();
_G('initmoney', initAccount.Equity);
}
// Accumulate invocation count
const invoketime = _G('invoketime') + 1;
_G('invoketime', invoketime);
// Calculate runtime duration (minutes)
const duringtime = Math.floor((Date.now() - _G('STARTTIME')) / 60000);
// Get current account information
const currentAccount = exchange.GetAccount();
const currentAccountValue = currentAccount.Equity;
// Calculate total return percentage
const initMoney = _G('initmoney');
const totalReturnPercent = ((currentAccountValue - initMoney) / initMoney * 100).toFixed(2);
// Log profit to system
LogProfit(currentAccountValue - initMoney, "&")
// Return 5 core metrics
return [{
json: {
invoketime: invoketime,
duringtime: duringtime,
totalReturnPercent: totalReturnPercent + '%',
availableCash: currentAccount.Balance.toFixed(2),
currentAccountValue: currentAccountValue.toFixed(2)
}
}];
Output Data Structure
json
{
"invoketime": 42, // System invocation count
"duringtime": 126, // Runtime duration (minutes)
"totalReturnPercent": "3.45%", // Total return percentage
"availableCash": "10345.67", // Available cash
"currentAccountValue": "10345.00" // Total account value
}
Design Highlights
Persistent State Management: Uses the _G() function to achieve cross-cycle data persistence
Baseline Anchoring: Records initial capital initmoney as the benchmark for profit calculation
Performance Visualization: Provides real-time profit feedback to system charts through the LogProfit() function
Defensive Programming: Automatically initializes on first run to avoid null value errors
5. Node 3: Market Data Acquisition
Functional Positioning
This is the "eyes" of the entire system, responsible for collecting, processing, and calculating various market data and technical indicators.
Core Logic Architecture
The market data acquisition node's functionality can be divided into three levels:
Level 1: Coin List Parsing and Loop Collection
javascript
// Parse coin list
const coins = $vars.coinList ?
($vars.coinList.includes(',') ? $vars.coinList.split(',') : [$vars.coinList]) : [];
if (coins.length === 0) {
return {};
}
// Fetch market data for each coin
const allCoinsData = {};
for (let i = 0; i < coins.length; i++) {
const coin = coins[i].trim();
try {
allCoinsData[coin] = getMarketDataForCoin(coin);
} catch (e) {
allCoinsData[coin] = { error: e.toString() };
}
}
return { data: allCoinsData };
Level 2: Multi-Timeframe Candlestick Data Acquisition and Indicator Calculation
javascript
function getMarketDataForCoin(symbol) {
// Switch to the corresponding coin's perpetual contract
exchange.SetCurrency(symbol + "_USDT");
exchange.SetContractType("swap");
// Fetch 3-minute and 4-hour candlestick data
const kline3m = exchange.GetRecords(60 * 3); // 3-minute timeframe
const kline4h = exchange.GetRecords(60 * 60 * 4); // 4-hour timeframe
// Data validity check
if (!kline3m || kline3m.length < 50 || !kline4h || kline4h.length < 50) {
return { error: "Insufficient candlestick data" };
}
// Calculate 3-minute timeframe technical indicators
const ema20_3m = TA.EMA(kline3m, 20); // 20-period Exponential Moving Average
const macd_3m = TA.MACD(kline3m, 12, 26, 9); // MACD indicator
const rsi7_3m = TA.RSI(kline3m, 7); // 7-period RSI
const rsi14_3m = TA.RSI(kline3m, 14); // 14-period RSI
// Calculate 4-hour timeframe technical indicators
const ema20_4h = TA.EMA(kline4h, 20); // 20-period EMA
const ema50_4h = TA.EMA(kline4h, 50); // 50-period EMA
const macd_4h = TA.MACD(kline4h, 12, 26, 9); // MACD indicator
const rsi14_4h = TA.RSI(kline4h, 14); // 14-period RSI
const atr3_4h = TA.ATR(kline4h, 3); // 3-period ATR (volatility)
const atr14_4h = TA.ATR(kline4h, 14); // 14-period ATR
// Get latest candlestick and recent 10 candlesticks
const latest3m = kline3m[kline3m.length - 1];
const latest4h = kline4h[kline4h.length - 1];
const recent10_3m = kline3m.slice(-10);
const recent10_4h = kline4h.slice(-10);
// Calculate average volume
const volumes4h = recent10_4h.map(k => k.Volume);
const avgVolume4h = volumes4h.reduce((a, b) => a + b, 0) / volumes4h.length;
// Return structured data...
}
Dual Timeframe Strategy:
- 3-minute short timeframe: Captures short-term fluctuations for precise entry and exit timing
- 4-hour long timeframe: Determines major trend direction to avoid counter-trend trading This multi-timeframe analysis is a standard configuration in professional quantitative trading, essentially providing the AI with both a "microscope" and a "telescope" perspective simultaneously.
Level 3: Structured Data Output
javascript
return {
symbol: symbol,
current_price: latest3m.Close,
current_ema20: ema20_3m[ema20_3m.length - 1],
current_macd: macd_3m[2][macd_3m[2].length - 1],
current_rsi_7: rsi7_3m[rsi7_3m.length - 1],
funding_rate: fundingRate,
intraday_3min: {
mid_prices: recent10_3m.map(k => k.Close),
ema_20_series: recent10_3m.map((k, i) => ema20_3m[ema20_3m.length - 10 + i]),
macd_series: recent10_3m.map((k, i) => macd_3m[2][macd_3m[2].length - 10 + i]),
rsi_7_series: recent10_3m.map((k, i) => rsi7_3m[rsi7_3m.length - 10 + i]),
rsi_14_series: recent10_3m.map((k, i) => rsi14_3m[rsi14_3m.length - 10 + i])
},
longer_term_4hour: {
ema_20: ema20_4h[ema20_4h.length - 1],
ema_50: ema50_4h[ema50_4h.length - 1],
atr_3: atr3_4h[atr3_4h.length - 1],
atr_14: atr14_4h[atr14_4h.length - 1],
current_volume: latest4h.Volume,
average_volume: avgVolume4h,
macd_series: recent10_4h.map((k, i) => macd_4h[2][macd_4h[2].length - 10 + i]),
rsi_14_series: recent10_4h.map((k, i) => rsi14_4h[rsi14_4h.length - 10 + i])
}
};
Technical Indicator Explanations
1、EMA (Exponential Moving Average)
- Purpose: Determine trend direction and support/resistance levels
- Price above EMA20 → Short-term bullish
EMA20 crosses above EMA50 → Golden cross, buy signal
2、MACD (Moving Average Convergence Divergence)Purpose: Determine momentum and trend reversals
MACD histogram turns from negative to positive → Momentum strengthening
DIF line crosses above DEA line → Golden cross signal
3、RSI (Relative Strength Index)Purpose: Identify overbought/oversold conditions
RSI > 70 → Overbought, possible pullback
RSI < 30 → Oversold, possible rebound
4、ATR (Average True Range)Purpose: Measure market volatility, used to adjust stop-loss distance
6. Node 4: Position Data Acquisition
Functional Positioning
The position data acquisition node is responsible for tracking the current position status of each coin, providing the AI with complete position information.
Core Code (Key Sections)
javascript
function getAllPositions() {
// Get current account equity
const curequity = exchange.GetAccount().Equity;
// Get coin list
const coins = $vars.coinList ?
($vars.coinList.includes(',') ? $vars.coinList.split(',') : [$vars.coinList]) : [];
// Calculate risk amount per coin = account equity / number of coins
const risk_usd = coins.length > 0 ? curequity / coins.length : 0;
// Get all actual positions
const rawPositions = exchange.GetPositions();
// Create position mapping table (coin symbol -> position object)
const positionMap = {};
if (rawPositions && rawPositions.length > 0) {
for (let pos of rawPositions) {
if (pos.Amount && Math.abs(pos.Amount) > 0) {
// Extract coin symbol (e.g., BTC_USDT.swap -> BTC)
const coinSymbol = pos.Symbol.replace('_USDT.swap', '')
.replace('.swap', '')
.replace('_USDT', '');
positionMap[coinSymbol] = pos;
}
}
}
// Create position information for each coin
const allPositions = [];
for (let i = 0; i < coins.length; i++) {
const coin = coins[i].trim();
const pos = positionMap[coin];
if (pos) {
// When position exists - build complete position information
// Get take-profit and stop-loss order IDs
const { tpOrderId, slOrderId } = getTPSLOrderIds(pos.Symbol, currentPrice, pos.Type);
// Get exit plan
const exitPlan = _G(`exit_plan_${pos.Symbol}`) || {
profit_target: null,
stop_loss: null,
invalidation_condition: ""
};
allPositions.push({
symbol: coin,
quantity: Math.abs(pos.Amount), // Position size
entry_price: pos.Price, // Entry price
current_price: currentPrice, // Current price
liquidation_price: /* Liquidation price calculation */,
unrealized_pnl: _N(pos.Profit, 2), // Unrealized P&L
leverage: pos.MarginLevel || 1, // Leverage multiplier
exit_plan: exitPlan, // Exit plan
confidence: exitPlan?.confidence || null,
risk_usd: risk_usd, // Risk amount
sl_oid: slOrderId, // Stop-loss order ID
tp_oid: tpOrderId, // Take-profit order ID
wait_for_fill: false,
entry_oid: pos.Info?.posId || -1,
notional_usd: _N(Math.abs(pos.Amount) * currentPrice, 2)
});
} else {
// When no position exists - set all fields to null
allPositions.push({
symbol: coin,
quantity: null, // Key field: null indicates no position
entry_price: null,
current_price: null,
liquidation_price: null,
unrealized_pnl: null,
leverage: null,
exit_plan: null,
confidence: null,
risk_usd: risk_usd, // Still return risk_usd for opening position calculations
sl_oid: null,
tp_oid: null,
wait_for_fill: false,
entry_oid: null,
notional_usd: null
});
}
}
return allPositions;
}
const positions = getAllPositions();
return {positions};
Key Design
Critical role of the quantity field:
- quantity = null: No position, AI can consider opening a position
- quantity ≠ null: Position exists, AI can only hold or close, cannot add to position This design avoids the risk of "pyramid position sizing" and ensures each coin has only one active position.
7. Node 5: Data Merging
Functional Positioning
Merges market data and position data into the complete context required for AI decision-making.
Source Code Implementation
javascript
// Get input data
const inputData = $input.all();
// First input is market data, second is position data
const marketData = inputData[0].json.data;
const positions = inputData[1].json;
// Return organized data
return [{
json: {
marketData: marketData,
positions: positions
}
}];
Simple and efficient data integration, providing a unified data interface for the AI.
8. Node 6: AI Agent (Core Decision Engine)
Functional Positioning
This is the core of the entire system—the AI decision engine. It receives complete market and account information and outputs specific trading instructions.

Prompt Architecture Explanation
The AI agent's decision-making relies on two types of prompts:
1、System Prompt (System Message):
- Source: Not publicly disclosed by NOF1 website, reverse-engineered from results
- Purpose: Defines the AI's role, behavioral rules, and decision-making framework, essentially the AI's "operating manual"
- Characteristics: Fixed and unchanging, identical for every call
Position: Passed in as a system message when calling the AI model
2、User Prompt (Text Prompt):Source: Publicly available from NOF1 website
Purpose: Provides dynamic market data and account status, essentially the AI's "real-time information input"
Characteristics: Different for each call, contains the latest market data and position information
Position: Passed in as a user message when calling the AI model
This dual-prompt architecture of "fixed rules + dynamic data" allows the AI to maintain a stable decision-making framework while responding flexibly to real-time market conditions.
System Prompt Detailed Explanation
The system prompt defines the AI's behavioral rules and decision-making framework, which can be divided into four core parts:
Part 1: Hard Constraint Rules
python
## HARD CONSTRAINTS
### Position Limits
- Tradable coins: {{$vars.coinList}}
- Maximum {{$vars.coinList.split(',').length}} concurrent positions
- No pyramiding or adding to existing positions
- Must be flat before re-entering a coin
### Risk Management
- Maximum risk per trade: 5% of account value
- Leverage range: 5x to 40x
- Minimum risk-reward ratio: 2:1
- Every position must have:
- Stop loss (specific price level)
- Profit target (specific price level)
- Invalidation condition (format: "If price closes below/above [PRICE] on a [TIMEFRAME] candle")
Design Philosophy:
Position Limit: Each coin holds a unidirectional position, forcing risk diversification
No Position Adding: Avoids the trap of "averaging down"
Risk Cap: Maximum 5% of account value at risk per trade
Risk-Reward Ratio: At least 2:1, meaning profit target must be at least 2x the stop-loss distance
Part 2: Decision Framework
mylang
## DECISION FRAMEWORK
### Identifying Position Status
A coin has an **active position** if `quantity` is NOT null.
A coin has **no position** if `quantity` is null.
### For Coins WITH Active Positions
Check each position in this order:
1. Invalidation condition triggered? → Close immediately
2. Stop loss or profit target hit? → Close
3. Technical setup still valid? → Hold
4. If uncertain → Hold (trust your exit plan)
Available signals: "hold" or "close" ONLY
### For Coins WITHOUT Positions
Only consider if:
- Current active positions < 6
- Available cash > $1000
- You see a high-probability setup
Available signal: "entry" ONLY
Logic Clarity:
- Strict distinction between "with position" and "no position" states
- With position: Can only choose "hold" or "close"
- No position: Can only choose "open" or "skip"
- This design prevents the AI from generating logically conflicting instructions Part 3: Output Format Specification
javascript
{
"BTC": {
"trade_signal_args": {
"coin": "BTC",
"signal": "entry|hold|close",
"profit_target": 115000.0,
"stop_loss": 112000.0,
"invalidation_condition": "If price closes below 112500 on a 3-minute candle",
"leverage": 15,
"confidence": 0.75,
"risk_usd": 624.38,
"justification": "Reason for this decision"
}
}
}
Field Descriptions:
- signal: Trading signal (entry/hold/close)
- profit_target: Take-profit price
- stop_loss: Stop-loss price
- invalidation_condition: Invalidation condition (natural language description)
- leverage: Leverage multiplier (5-40)
- confidence: AI's confidence in this signal (0-1)
- risk_usd: Risk amount willing to take
- justification: Decision rationale (for auditing and debugging) Part 4: Thought Process Guidance
python
## THINKING PROCESS
Before outputting JSON, think through your decisions step by step:
1. Identify position status for each coin
2. Review coins WITH active positions
3. Review coins WITHOUT positions
4. Output final decisions in JSON
This "Chain of Thought" prompting makes the AI analyze before outputting, improving decision stability and interpretability.
User Prompt Detailed Explanation (Dynamic Data Input)
Source Explanation: The user prompt uses template syntax to dynamically inject real-time data.
The user prompt is dynamically generated with the latest market conditions and account information on each call:
python
It has been {{ duringtime }} minutes since you started trading.
The current time is {{ $now.toISO() }}
You've been invoked {{ invoketime }} times.
ALL OF THE PRICE OR SIGNAL DATA BELOW IS ORDERED: OLDEST - NEWEST
Timeframes note: Unless stated otherwise in a section title, intraday series
are provided at 3 minute intervals. If a coin uses a different interval, it is
explicitly stated in that coin's section.
**CURRENT MARKET STATE FOR ALL COINS**
{{ JSON.stringify(marketData) }}
**HERE IS YOUR ACCOUNT INFORMATION & PERFORMANCE**
Current Total Return (percent): {{ totalReturnPercent }}
Available Cash: {{ availableCash }}
Current Account Value: {{ currentAccountValue }}
Current live positions & performance:
{{ JSON.stringify(positions) }}
Prompt Data Flow Detailed Explanation
This design ensures the AI receives complete decision-making context each time:
1、Time Awareness
- Runtime duration (duringtime minutes)
- Current timestamp ($now.toISO())
Invocation count (invoketime times)
2、Market Data (from "Market Data Acquisition" node)3-minute and 4-hour candlestick data for each coin
Technical indicator series for the most recent 10 candlesticks
Real-time indicators like current price, EMA, MACD, RSI, etc.
3、Account Status (from "Parameter Reset" node)Total return percentage (totalReturnPercent)
Available cash (availableCash)
Total account value (currentAccountValue)
4、Position Details (from "Position Data Acquisition" node)Position quantity for each coin (quantity field)
Entry price, current price, unrealized P&L
Take-profit/stop-loss plans, risk amount
Complete Prompt Workflow
python
┌─────────────────────────────────────────────────────────────┐
│ AI Model Invocation Moment │
├─────────────────────────────────────────────────────────────┤
│ │
│ System Prompt (Fixed) │
│ ┌────────────────────────────────────────────┐ │
│ │ You are an expert cryptocurrency trader... │ │
│ │ ## HARD CONSTRAINTS │ │
│ │ - Maximum 6 positions │ │
│ │ - Risk per trade: 5% max │ │
│ │ ## DECISION FRAMEWORK │ │
│ │ - For coins WITH positions: hold/close │ │
│ │ - For coins WITHOUT positions: entry │ │
│ │ ## OUTPUT FORMAT │ │
│ │ - JSON with trade_signal_args │ │
│ └────────────────────────────────────────────┘ │
│ ↓ │
│ User Prompt (Dynamic, different each time) │
│ ┌────────────────────────────────────────────┐ │
│ │ Running for 126 minutes, invoked 42 times │ │
│ │ Current Total Return: 3.45% │ │
│ │ Available Cash: $10,345.67 │ │
│ │ │ │
│ │ Market Data: │ │
│ │ { │ │
│ │ "BTC": { │ │
│ │ "current_price": 67234.5, │ │
│ │ "current_ema20": 67150.2, │ │
│ │ "current_macd": -141.87, │ │
│ │ "current_rsi_7": 52.93, │ │
│ │ "intraday_3min": {...}, │ │
│ │ "longer_term_4hour": {...} │ │
│ │ }, │ │
│ │ "ETH": {...}, ... │ │
│ │ } │ │
│ │ │ │
│ │ Positions: │ │
│ │ [ │ │
│ │ { │ │
│ │ "symbol": "BTC", │ │
│ │ "quantity": 0.5, │ │
│ │ "entry_price": 66800.0, │ │
│ │ "unrealized_pnl": 217.25, │ │
│ │ "exit_plan": { │ │
│ │ "stop_loss": 66000.0, │ │
│ │ "profit_target": 68500.0 │ │
│ │ } │ │
│ │ }, │ │
│ │ { │ │
│ │ "symbol": "ETH", │ │
│ │ "quantity": null, // No position │ │
│ │ ... │ │
│ │ } │ │
│ │ ] │ │
│ └────────────────────────────────────────────┘ │
│ ↓ │
│ AI Model Processing and Reasoning │
│ ↓ │
│ AI Output (JSON Format) │
│ ┌────────────────────────────────────────────┐ │
│ │ { │ │
│ │ "BTC": { │ │
│ │ "trade_signal_args": { │ │
│ │ "signal": "hold", │ │
│ │ "justification": "Position valid..." │ │
│ │ } │ │
│ │ }, │ │
│ │ "ETH": { │ │
│ │ "trade_signal_args": { │ │
│ │ "signal": "entry", │ │
│ │ "profit_target": 2800.0, │ │
│ │ "stop_loss": 2600.0, │ │
│ │ "leverage": 15, │ │
│ │ "risk_usd": 833.33, │ │
│ │ "justification": "Bullish setup..." │ │
│ │ } │ │
│ │ } │ │
│ │ } │ │
│ └────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
↓
Passed to "Trade Execution" Node
Advantages of This Dual-Prompt Architecture:
- Rule Stability: System prompt is fixed, ensuring the AI's behavioral rules remain consistent
- Data Timeliness: User prompt updates dynamically, ensuring the AI makes decisions based on the latest market conditions
- Separation of Concerns: Rule definition and data input are separated, facilitating debugging and optimization
- Scalability: System prompt can be modified at any time to optimize strategy without affecting data flow
- Auditability: Complete input and output of each AI call can be logged and traced back
9. Node 7: Trade Execution
Functional Positioning
This is the "hands" of the workflow, responsible for translating AI decisions into actual exchange orders and continuously monitoring take-profit and stop-loss conditions.
Core Execution Logic
The trade execution node is divided into five functional modules:
Module 1: Signal Parsing and Validation
javascript
// ========== Utility Functions ==========
function parseAIOutput(output) {
try {
// Clean code block markers from output
const cleaned = output.replace(/```
[a-z]*\n?/gi, '').trim();
const start = cleaned.indexOf('{');
const end = cleaned.lastIndexOf('}');
return JSON.parse(cleaned.substring(start, end + 1));
} catch (e) {
return {};
}
}
// Main logic
const signals = parseAIOutput($input.first().json.output);
Log(signals)
Exception Handling:
- Catches JSON parsing errors
- Cleans markdown formatting from AI output
- Prevents system crashes due to AI output format issues Module 2: Precision Management and Position Calculation
javascript
// Get trading pair precision information
function getPrecision(coin) {
try {
const symbol = coin + '_USDT.swap';
const markets = exchange.GetMarkets();
if (markets && markets[symbol]) {
return {
price: markets[symbol].PricePrecision || 0,
amount: markets[symbol].AmountPrecision || 0,
minQty: markets[symbol].MinQty || 5
};
}
return { price: 0, amount: 0, minQty: 5 };
} catch (e) {
Log(`⚠️ Failed to get ${coin} precision, using default values`);
return { price: 0, amount: 0, minQty: 5 };
}
}
// Calculate position size
function calculateQuantity(entryPrice, stopLoss, riskUsd, leverage, precision) {
const riskPerContract = Math.abs(entryPrice - stopLoss);
if (riskPerContract <= 0) return 0;
// Calculate quantity based on risk amount
const quantity = riskUsd / riskPerContract;
// Limit maximum position = (account balance × leverage / 6) / entry price
const maxQuantity = (exchange.GetAccount().Balance * leverage / 6) / entryPrice;
let finalQuantity = Math.min(quantity, maxQuantity);
// Apply precision and minimum quantity limits
if (precision) {
finalQuantity = _N(finalQuantity, precision.amount);
if (finalQuantity < precision.minQty) {
Log(`⚠️ Calculated quantity ${finalQuantity} is less than minimum order quantity ${precision.minQty}`);
return 0;
}
}
return finalQuantity;
}
Position Calculation Formula:
python
Risk Distance = |Entry Price - Stop Loss Price|
Position Size = Risk Amount ÷ Risk Distance
Maximum Position = (Account Balance × Leverage ÷ 6) ÷ Entry Price
Final Position = min(Position Size, Maximum Position)
This calculation method ensures:
- Regardless of price level, the risk amount remains constant
- When stop-loss is triggered, the loss equals exactly the preset risk amount
- Prevents excessive position size due to high leverage Module 3: Opening Position Execution
javascript
function executeEntry(coin, args) {
exchange.SetCurrency(coin + '_USDT');
exchange.SetContractType("swap");
const ticker = exchange.GetTicker();
if (!ticker) return;
const currentPrice = ticker.Last;
if (!validateEntry(coin, currentPrice, args.profit_target, args.stop_loss)) return;
const leverage = args.leverage || 10;
exchange.SetMarginLevel(leverage);
precision = getPrecision(coin);
quantity = calculateQuantity(currentPrice, args.stop_loss, args.risk_usd, leverage, precision);
if (quantity <= 0) {
Log(`⚠️ ${coin}: Calculated quantity invalid, skipping entry`);
return;
}
const isLong = args.profit_target > args.stop_loss;
exchange.SetDirection(isLong ? "buy" : "sell");
const orderId = isLong ? exchange.Buy(-1, quantity) : exchange.Sell(-1, quantity);
if (orderId) {
Sleep(1000);
Log(`✅ ${coin}: Opened ${isLong ? 'Long' : 'Short'} Quantity=${quantity} Leverage=${leverage}x Precision=${precision.amount}`);
} else {
Log(`❌ ${coin}: Failed to open position`, precision.amount);
}
}
Module 4: Closing Position Execution
javascript
function executeClose(coin) {
exchange.SetCurrency(coin + '_USDT');
exchange.SetContractType("swap");
// Cancel all pending orders
const orders = exchange.GetOrders();
orders?.forEach(o => exchange.CancelOrder(o.Id));
// Get position information
const pos = exchange.GetPositions().find(p =>
p.Symbol.includes(coin) && Math.abs(p.Amount) > 0
);
if (!pos) return;
const isLong = pos.Type === PD_LONG || pos.Type === 0;
const precision = getPrecision(coin);
// Apply precision to closing quantity
const closeAmount = _N(Math.abs(pos.Amount), precision.amount);
exchange.SetDirection(isLong ? "closebuy" : "closesell");
const orderId = isLong ?
exchange.Sell(-1, closeAmount) :
exchange.Buy(-1, closeAmount);
if (orderId) {
Log(`✅ ${coin}: Successfully closed ${isLong ? 'Long' : 'Short'}, Quantity=${closeAmount}`);
_G(`exit_plan_${coin}_USDT.swap`, null);
}
}
Module 5: Take-Profit and Stop-Loss Monitoring
javascript
function monitorPosition(coin) {
exchange.SetCurrency(coin + '_USDT');
exchange.SetContractType("swap");
const pos = exchange.GetPositions().find(p =>
p.Symbol.includes(coin) && Math.abs(p.Amount) > 0
);
if (!pos) return;
const ticker = exchange.GetTicker();
if (!ticker) return;
const isLong = pos.Type === PD_LONG || pos.Type === 0;
const currentPrice = ticker.Last;
// Calculate profit/loss percentage
const pnl = (currentPrice - pos.Price) * (isLong ? 1 : -1) / pos.Price;
// Get exit plan
const exitPlan = _G(`exit_plan_${coin}_USDT.swap`);
if (!exitPlan?.profit_target || !exitPlan?.stop_loss) {
// If no exit plan is set, use default values
if (pnl >= 0.03) return closePosition(coin, pos, isLong, "Take Profit", pnl);
if (pnl <= -0.01) return closePosition(coin, pos, isLong, "Stop Loss", pnl);
return;
}
// Check take-profit condition
const shouldTP = isLong ?
currentPrice >= exitPlan.profit_target :
currentPrice <= exitPlan.profit_target;
// Check stop-loss condition
const shouldSL = isLong ?
currentPrice <= exitPlan.stop_loss :
currentPrice >= exitPlan.stop_loss;
if (shouldTP) return closePosition(coin, pos, isLong, "Take Profit", pnl);
if (shouldSL) return closePosition(coin, pos, isLong, "Stop Loss", pnl);
}
function closePosition(coin, pos, isLong, reason, pnl) {
const precision = getPrecision(coin);
const closeAmount = _N(Math.abs(pos.Amount), precision.amount);
exchange.SetDirection(isLong ? "closebuy" : "closesell");
isLong ? exchange.Sell(-1, closeAmount) : exchange.Buy(-1, closeAmount);
Log(`${reason === 'Take Profit' ? '✅' : '❌'} ${coin} ${reason} ${(pnl*100).toFixed(2)}%`);
_G(`exit_plan_${coin}_USDT.swap`, null);
}
Module 6: Visualization Design
To facilitate understanding of the AI trading operation logic, the AI trading signal analysis and position status are presented visually.
10. Key Design Highlights
1. The Power of Multi-Timeframe Analysis
The system simultaneously uses 3-minute and 4-hour timeframes, which is not simple data redundancy:
Example Scenario:
- 4-hour chart shows BTC in an uptrend (price above EMA20)
- 3-minute chart shows a pullback (short-term price decline)
Decision: This is a "pullback within a trend," representing an opportunity to add positions rather than a risk signal
Dual Timeframe Coordination:4-hour determines direction (long or short)
3-minute identifies entry points (when to enter)
2. Three Lines of Defense in Risk Management
First Line: Capital Allocation
javascript
Maximum risk per trade = Account value ÷ Number of coins
Maximum 6 positions = Theoretical maximum total risk 30%
Actual maximum risk < 30% (not all 6 stop-losses will trigger simultaneously)
Second Line: Stop-Loss Setup
javascript
Stop-loss distance = |Entry price - Stop-loss price| / Entry price
Typical setting: 2-5%
Combined with leverage: At 10x leverage, 5% price movement = 50% principal movement
Third Line: Invalidation Conditions
javascriptExample: "If price closes below $66,500 on the 3-minute candlestick"
Purpose: Exit even if stop-loss hasn't triggered when technical pattern breaks
3. Engineering of AI Output Format
Why require JSON format?
- Structured data is easy to parse
- Avoids ambiguity of natural language
Facilitates automated validation and processing
Why enforce field consistency?Ensures all signals contain the same field structure
Simplifies parsing code logic
Avoids errors due to missing fields
11. System Limitations and Improvement Directions
Current Limitations
1、Cannot Handle Sudden Events
- AI only looks at technical indicators, doesn't consider news or policy
Cannot respond to black swan events (e.g., exchange hacks)
2、Fixed Cycle Limitations3-minute trigger may miss rapid fluctuations
May also generate excessive trades in calm markets
3、Leverage Risk5-40x leverage can lead to rapid liquidation in extreme market conditions
Even with stop-loss, slippage may cause losses beyond expectations
4、AI Model StabilityLarge language model outputs have randomness
Same input may yield different decisions
Possible Improvement Directions
1、Introduce News Sentiment AnalysisIntegrate cryptocurrency news sources
Use NLP to analyze market sentiment
2、Dynamically Adjust Trigger FrequencyIncrease check frequency during high volatility
Decrease frequency during low volatility to save resources
3、Multi-Model Voting MechanismRun multiple AI models simultaneously
Make decisions based on consensus from multiple models
4、Add Backtesting ValidationValidate strategy on historical data
Optimize prompts and parameters
12. Conclusion
This AI quantitative trading system demonstrates how to apply large language models to real financial trading scenarios. Its core advantages include:
- Modular Design: Each node has clear responsibilities, easy to maintain and extend
- Strict Risk Control: Multi-layer protection mechanisms to avoid single major losses
- Engineered AI Integration: Structured input/output, reliable signal parsing
Complete Closed Loop: Full automation from data collection to order execution
Key Insights:AI is not omnipotent; it requires strict constraints and rules
Risk management is more important than prediction accuracy
System reliability is more critical than strategy complexity
I hope this detailed technical breakdown helps you understand the operational logic of AI quantitative trading and make wiser decisions in your own practice.
Appendix: Complete Source Code and Resources
Complete Source Code and Live Trading Records:
- FMZ Quant Platform: https://www.fmz.com/strategy/512801
- Live Trading Address: https://www.fmz.com/robot/623016
You can replace different AI models, adjust prompts, and select trading coins
Risk Warning:This article is for technical learning only and does not constitute investment advice
Cryptocurrency trading carries extremely high risks and may result in total loss of principal
Always conduct thorough testing before using real funds

Top comments (0)