这是一套AI自动交易系统,由两部分组成: - 大脑端:ClawdBot 负责数据采集、新闻分析、交易决策 - 执行端:发明者量化平台(FMZ)负责接收信号、执行交易、风控管理
在策略代码中配置唯一的通道标识符:
const CONFIG = {
UUID: "自定义UUID", // 替换为你自己的UUID,例如:"6BC42A119B5DBFA2188A8279DA3B5C30"
TRADE_AMOUNT: 0.01, // 每次交易数量
CHECK_INTERVAL: 3000, // 检查间隔(毫秒)
STOP_LOSS_PERCENT: 5, // 止损比例(%)
};
UUID生成方式:可以使用任意32位十六进制字符串,确保唯一性即可。
648365)启动后日志显示:
🚀 现货自动交易机器人启动
⚙️ 配置: 交易量=0.01, 止损比例=5%
📡 监听频道: 6BC42A119B5DBFA2188A8279DA3B5C30
ClawdBot 通过 HTTP POST 请求发送交易信号到 FMZ 平台。
https://www.fmz.com/api/v1?method=pub&robot={实盘ID}&channel={UUID}
https://www.fmz.com/api/v1?method=pub&robot=666666&channel=6BC42A119B5DBFA2188A8279DA3B5C30
POST
Content-Type: application/json
| 字段名 | 类型 | 说明 | 示例值 |
|---|---|---|---|
coin |
string | 币种代码 | "BTC" |
timestamp |
string | ISO格式时间戳 | "2024-01-15T14:00:00.000Z" |
current_price |
number | 当前价格 | 42500.00 |
trade_decision |
string | 交易决策 | "买入" / "卖出" / "观望" |
decision_reason |
string | 决策原因 | "新闻情绪积极..." |
| 字段名 | 类型 | 说明 | 示例值 |
|---|---|---|---|
volume_24h |
string | 24小时交易量 | "25,000,000,000" |
news_summary |
string | 新闻汇总 | "ETF资金流入..." |
news_sentiment |
string | 新闻情绪 | "positive" / "negative" / "neutral" |
{
"coin": "BTC",
"timestamp": "2024-01-15T14:00:00.000Z",
"current_price": 42500.00,
"volume_24h": "25,000,000,000",
"news_summary": "ETF资金持续流入,机构增持意愿强烈,市场情绪乐观",
"news_sentiment": "positive",
"trade_decision": "买入",
"decision_reason": "新闻情绪积极,交易量放大,适合建仓"
}
┌─────────────────────────────────────────────────────────────┐
│ ClawdBot (大脑端) │
│ 1. 采集实时数据 │
│ 2. 分析新闻情绪 │
│ 3. 生成交易决策JSON │
│ 4. HTTP POST发送到FMZ │
└─────────────────────────────────────────────────────────────┘
│
▼
HTTP POST Request
│
▼
┌─────────────────────────────────────────────────────────────┐
│ FMZ策略 (执行端) │
│ 1. GetChannelData() 监听频道 │
│ 2. 解析JSON信号 │
│ 3. 检查时间戳去重(防止重复执行) │
│ 4. 根据trade_decision执行操作: │
│ - "买入" → executeBuy() │
│ - "卖出" → executeSell() │
│ - "观望" → 仅记录日志 │
│ 5. 更新仪表板显示 │
│ 6. 持续检查止损条件 │
└─────────────────────────────────────────────────────────────┘
通过 timestamp 字段判断信号是否已处理,防止同一信号重复执行。
策略运行时会实时显示四个表格:
| 表格 | 内容 |
|---|---|
| 💰 权益概览 | 初始/当前币数、U数、权益、盈亏 |
| 🛡️ 止损监控 | 最新交易、价格变动、距止损距离 |
| 🤖 当前AI信号 | 最新收到的决策信息 |
| 📋 交易记录 | 最近10条交易详情 |
https://www.fmz.com/api/v1?method=pub&robot={你的实盘ID}&channel={你的UUID}
// ========== 现货自动交易机器人 + 可视化仪表板 ==========
// ========== 配置参数 ==========
const CONFIG = {
TRADE_AMOUNT: 0.01, // 每次交易数量
CHECK_INTERVAL: 3000, // 检查间隔(毫秒)
UUID: "自定义UUID", // 接收CLAWDBOT频道
STOP_LOSS_PERCENT: 5, // 止损比例(%)
};
// ========== 初始化 ==========
function initialize() {
// 初始化权益记录
if (_G('initData') === null) {
exchange.SetCurrency("BTC_USDT");
const account = _C(exchange.GetAccount);
const ticker = _C(exchange.GetTicker);
const initEquity = account.Stocks * ticker.Last + account.Balance;
_G('initData', {
initStocks: account.Stocks,
initBalance: account.Balance,
initEquity: initEquity,
initTime: new Date().toISOString()
});
Log(`📊 初始化完成 - 初始币数: ${account.Stocks}, 初始U数: ${account.Balance}, 初始权益: $${initEquity.toFixed(2)}`);
}
// 初始化交易记录
if (_G('tradeRecords') === null) {
_G('tradeRecords', []);
}
// 初始化已处理的信号时间戳
if (_G('processedTimestamps') === null) {
_G('processedTimestamps', []);
}
}
// ========== 检查信号是否已处理 ==========
function isSignalProcessed(timestamp) {
const processedTimestamps = _G('processedTimestamps') || [];
return processedTimestamps.includes(timestamp);
}
// ========== 记录已处理的信号时间戳 ==========
function markSignalProcessed(timestamp) {
let processedTimestamps = _G('processedTimestamps') || [];
processedTimestamps.unshift(timestamp);
// 只保留最近100条
if (processedTimestamps.length > 100) {
processedTimestamps = processedTimestamps.slice(0, 100);
}
_G('processedTimestamps', processedTimestamps);
}
// ========== 接收AI信号 ==========
function receiveSignal() {
try {
const res = GetChannelData(CONFIG.UUID);
if (res === null || res === "") {
return null;
}
const signal = typeof res === 'string' ? JSON.parse(res) : res;
if (!signal.coin || !signal.trade_decision) {
Log("❌ 信号格式无效: ", signal);
return null;
}
// 检查时间戳是否已处理
if (isSignalProcessed(signal.timestamp)) {
return null;
}
Log(`📥 收到新信号: ${signal.coin} - ${signal.trade_decision} (${signal.timestamp})`);
_G('latestSignal', signal);
return signal;
} catch (e) {
Log(`❌ 获取信号失败: ${e.message}`);
return null;
}
}
// ========== 执行买入 ==========
function executeBuy(signal, reason) {
try {
const symbol = signal.coin + "_USDT";
exchange.SetCurrency(symbol);
const account = _C(exchange.GetAccount);
const ticker = _C(exchange.GetTicker);
const currentPrice = ticker.Last;
const requiredBalance = currentPrice * CONFIG.TRADE_AMOUNT;
if (account.Balance < requiredBalance) {
Log(`❌ 余额不足,需要 $${requiredBalance.toFixed(2)},当前余额 $${account.Balance.toFixed(2)}`);
return false;
}
const orderId = exchange.Buy(-1, CONFIG.TRADE_AMOUNT * currentPrice);
if (orderId) {
Sleep(1000);
const newTicker = _C(exchange.GetTicker);
const buyPrice = newTicker.Last;
// 添加交易记录
addTradeRecord({
coin: signal.coin,
action: "买入",
price: buyPrice,
amount: CONFIG.TRADE_AMOUNT,
reason: reason || signal.decision_reason,
timestamp: new Date().toISOString()
});
Log(`✅ ${signal.coin} 买入成功 - 价格: $${buyPrice.toFixed(2)}, 数量: ${CONFIG.TRADE_AMOUNT}`);
return true;
} else {
Log(`❌ ${signal.coin} 买入失败`);
return false;
}
} catch (e) {
Log(`❌ 买入异常: ${e.message}`);
return false;
}
}
// ========== 执行卖出 ==========
function executeSell(signal, reason) {
try {
const symbol = signal.coin + "_USDT";
exchange.SetCurrency(symbol);
const account = _C(exchange.GetAccount);
const ticker = _C(exchange.GetTicker);
const currentPrice = ticker.Last;
// 检查币是否足够
if (account.Stocks < CONFIG.TRADE_AMOUNT) {
Log(`❌ ${signal.coin} 余额不足,需要 ${CONFIG.TRADE_AMOUNT},当前 ${account.Stocks}`);
return false;
}
const orderId = exchange.Sell(-1, CONFIG.TRADE_AMOUNT);
if (orderId) {
// 添加交易记录
addTradeRecord({
coin: signal.coin,
action: "卖出",
price: currentPrice,
amount: CONFIG.TRADE_AMOUNT,
reason: reason || signal.decision_reason,
timestamp: new Date().toISOString()
});
Log(`✅ ${signal.coin} 卖出成功 - 价格: $${currentPrice.toFixed(2)}, 数量: ${CONFIG.TRADE_AMOUNT}`);
return true;
} else {
Log(`❌ ${signal.coin} 卖出失败`);
return false;
}
} catch (e) {
Log(`❌ 卖出异常: ${e.message}`);
return false;
}
}
// ========== 添加交易记录 ==========
function addTradeRecord(record) {
let records = _G('tradeRecords') || [];
records.unshift(record);
// 只保留最近10条
if (records.length > 10) {
records = records.slice(0, 10);
}
_G('tradeRecords', records);
}
// ========== 获取最新一笔交易记录 ==========
function getLatestTradeRecord() {
const records = _G('tradeRecords') || [];
// 查找最新一笔买入或卖出(排除观望)
for (let i = 0; i < records.length; i++) {
if (records[i].action === "买入" || records[i].action === "卖出") {
return records[i];
}
}
return null;
}
// ========== 检查止损 ==========
function checkStopLoss() {
try {
const latestTrade = getLatestTradeRecord();
// 没有交易记录,不需要止损
if (!latestTrade) {
return { triggered: false };
}
const coin = latestTrade.coin;
const symbol = coin + "_USDT";
exchange.SetCurrency(symbol);
const ticker = _C(exchange.GetTicker);
const currentPrice = ticker.Last;
const tradePrice = latestTrade.price;
// 计算价格变动百分比
const priceChangePercent = ((currentPrice - tradePrice) / tradePrice) * 100;
// 场景一:最新是买入,价格下跌触发止损卖出
if (latestTrade.action === "买入") {
const stopLossPrice = tradePrice * (1 - CONFIG.STOP_LOSS_PERCENT / 100);
if (currentPrice <= stopLossPrice) {
Log(`🔴 止损触发!${coin} 买入价: $${tradePrice.toFixed(2)}, 当前价: $${currentPrice.toFixed(2)}, 跌幅: ${priceChangePercent.toFixed(2)}%`);
return {
triggered: true,
action: "卖出",
coin: coin,
reason: `止损卖出:跌幅${priceChangePercent.toFixed(2)}%,触发${CONFIG.STOP_LOSS_PERCENT}%止损线`
};
}
}
// 场景二:最新是卖出,价格上涨触发止损买入(踏空保护)
if (latestTrade.action === "卖出") {
const stopLossPrice = tradePrice * (1 + CONFIG.STOP_LOSS_PERCENT / 100);
if (currentPrice >= stopLossPrice) {
Log(`🟢 踏空止损触发!${coin} 卖出价: $${tradePrice.toFixed(2)}, 当前价: $${currentPrice.toFixed(2)}, 涨幅: ${priceChangePercent.toFixed(2)}%`);
return {
triggered: true,
action: "买入",
coin: coin,
reason: `踏空止损:涨幅${priceChangePercent.toFixed(2)}%,触发${CONFIG.STOP_LOSS_PERCENT}%止损线`
};
}
}
return { triggered: false };
} catch (e) {
Log(`❌ 检查止损异常: ${e.message}`);
return { triggered: false };
}
}
// ========== 执行止损操作 ==========
function executeStopLoss(stopLossInfo) {
if (!stopLossInfo.triggered) {
return false;
}
const signal = {
coin: stopLossInfo.coin,
decision_reason: stopLossInfo.reason
};
if (stopLossInfo.action === "卖出") {
return executeSell(signal, stopLossInfo.reason);
} else if (stopLossInfo.action === "买入") {
return executeBuy(signal, stopLossInfo.reason);
}
return false;
}
// ========== 处理交易信号 ==========
function processSignal(signal) {
if (!signal) {
return { executed: false, reason: "无信号" };
}
const decision = signal.trade_decision;
const coin = signal.coin;
// 标记此信号已处理
markSignalProcessed(signal.timestamp);
switch (decision) {
case "买入":
const buySuccess = executeBuy(signal, signal.decision_reason);
return { executed: buySuccess, action: "buy", coin: coin, reason: signal.decision_reason };
case "卖出":
const sellSuccess = executeSell(signal, signal.decision_reason);
return { executed: sellSuccess, action: "sell", coin: coin, reason: signal.decision_reason };
case "观望":
Log(`⏸️ ${coin} 观望 - 原因: ${signal.decision_reason}`);
addTradeRecord({
coin: coin,
action: "观望",
price: signal.current_price,
amount: 0,
reason: signal.decision_reason,
timestamp: new Date().toISOString()
});
return { executed: false, action: "hold", coin: coin, reason: signal.decision_reason };
default:
return { executed: false, reason: "未知决策" };
}
}
// ========== 创建权益表格 ==========
function createEquityTable() {
const equityTable = {
type: "table",
title: "💰 权益概览",
cols: ["初始币数", "初始U数", "初始权益", "当前币数", "当前U数", "当前权益", "盈亏"],
rows: []
};
try {
const initData = _G('initData');
exchange.SetCurrency("BTC_USDT");
const account = _C(exchange.GetAccount);
const ticker = _C(exchange.GetTicker);
const currentEquity = account.Stocks * ticker.Last + account.Balance;
const pnl = currentEquity - initData.initEquity;
const pnlPercent = (pnl / initData.initEquity * 100).toFixed(2);
let pnlDisplay = "";
if (pnl > 0) {
pnlDisplay = `🟢 +$${pnl.toFixed(2)} (+${pnlPercent}%)`;
} else if (pnl < 0) {
pnlDisplay = `🔴 $${pnl.toFixed(2)} (${pnlPercent}%)`;
} else {
pnlDisplay = `⚪ $0 (0%)`;
}
equityTable.rows.push([
`${initData.initStocks.toFixed(8)}`,
`$${initData.initBalance.toFixed(2)}`,
`$${initData.initEquity.toFixed(2)}`,
`${account.Stocks.toFixed(8)}`,
`$${account.Balance.toFixed(2)}`,
`$${currentEquity.toFixed(2)}`,
pnlDisplay
]);
LogProfit(pnl, "&");
} catch (e) {
Log(`❌ 创建权益表失败: ${e.message}`);
equityTable.rows.push(["错误", "错误", "错误", "错误", "错误", "错误", "错误"]);
}
return equityTable;
}
// ========== 创建交易记录表格 ==========
function createTradeRecordsTable() {
const tradeTable = {
type: "table",
title: "📋 最近10条交易记录",
cols: ["时间", "币种", "执行操作", "价格", "数量", "交易原因"],
rows: []
};
try {
const records = _G('tradeRecords') || [];
if (records.length === 0) {
tradeTable.rows.push(["-", "-", "-", "-", "-", "暂无交易记录"]);
} else {
records.forEach(record => {
let actionDisplay = "";
switch (record.action) {
case "买入":
actionDisplay = "📈 买入";
break;
case "卖出":
actionDisplay = "📉 卖出";
break;
case "观望":
actionDisplay = "⏸️ 观望";
break;
default:
actionDisplay = record.action;
}
const time = record.timestamp ?
new Date(record.timestamp).toLocaleString('zh-CN', {
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
}) : "-";
const reason = record.reason && record.reason.length > 25 ?
record.reason.substring(0, 25) + "..." : (record.reason || "-");
tradeTable.rows.push([
time,
record.coin,
actionDisplay,
record.price ? `$${parseFloat(record.price).toFixed(2)}` : "-",
record.amount > 0 ? record.amount.toString() : "-",
reason
]);
});
}
} catch (e) {
Log(`❌ 创建交易记录表失败: ${e.message}`);
tradeTable.rows.push(["-", "-", "-", "-", "-", e.message]);
}
return tradeTable;
}
// ========== 创建当前信号表格 ==========
function createSignalTable() {
const signalTable = {
type: "table",
title: "🤖 当前AI信号",
cols: ["币种", "价格", "新闻汇总", "情绪", "决策", "原因"],
rows: []
};
try {
const signal = _G('latestSignal');
if (!signal) {
signalTable.rows.push(["-", "-", "等待信号...", "-", "⏳ 等待", "-"]);
} else {
let sentimentDisplay = "";
switch (signal.news_sentiment) {
case "positive":
sentimentDisplay = "🟢 积极";
break;
case "negative":
sentimentDisplay = "🔴 消极";
break;
default:
sentimentDisplay = "⚪ 中性";
}
let decisionDisplay = "";
switch (signal.trade_decision) {
case "买入":
decisionDisplay = "📈 买入";
break;
case "卖出":
decisionDisplay = "📉 卖出";
break;
default:
decisionDisplay = "⏸️ 观望";
}
const newsSummary = signal.news_summary && signal.news_summary.length > 35 ?
signal.news_summary.substring(0, 35) + "..." : (signal.news_summary || "-");
const reason = signal.decision_reason && signal.decision_reason.length > 25 ?
signal.decision_reason.substring(0, 25) + "..." : (signal.decision_reason || "-");
signalTable.rows.push([
signal.coin,
`$${signal.current_price}`,
newsSummary,
sentimentDisplay,
decisionDisplay,
reason
]);
}
} catch (e) {
Log(`❌ 创建信号表失败: ${e.message}`);
signalTable.rows.push(["错误", "-", "-", "-", "-", e.message]);
}
return signalTable;
}
// ========== 创建止损监控表格 ==========
function createStopLossTable() {
const stopLossTable = {
type: "table",
title: "🛡️ 止损监控",
cols: ["最新交易", "币种", "交易价格", "当前价格", "价格变动", "止损线", "状态"],
rows: []
};
try {
const latestTrade = getLatestTradeRecord();
if (!latestTrade) {
stopLossTable.rows.push(["-", "-", "-", "-", "-", "-", "暂无交易"]);
} else {
const coin = latestTrade.coin;
const symbol = coin + "_USDT";
exchange.SetCurrency(symbol);
const ticker = _C(exchange.GetTicker);
const currentPrice = ticker.Last;
const tradePrice = latestTrade.price;
// 计算价格变动
const priceChange = currentPrice - tradePrice;
const priceChangePercent = ((priceChange) / tradePrice) * 100;
let priceChangeDisplay = "";
if (priceChange > 0) {
priceChangeDisplay = `🟢 +$${priceChange.toFixed(2)} (+${priceChangePercent.toFixed(2)}%)`;
} else if (priceChange < 0) {
priceChangeDisplay = `🔴 $${priceChange.toFixed(2)} (${priceChangePercent.toFixed(2)}%)`;
} else {
priceChangeDisplay = `⚪ $0 (0%)`;
}
// 计算止损线
let stopLossPrice = 0;
let stopLossDisplay = "";
let statusDisplay = "";
if (latestTrade.action === "买入") {
stopLossPrice = tradePrice * (1 - CONFIG.STOP_LOSS_PERCENT / 100);
stopLossDisplay = `$${stopLossPrice.toFixed(2)} (跌${CONFIG.STOP_LOSS_PERCENT}%)`;
if (currentPrice <= stopLossPrice) {
statusDisplay = "🚨 触发止损";
} else {
const distancePercent = ((currentPrice - stopLossPrice) / stopLossPrice * 100).toFixed(2);
statusDisplay = `✅ 安全 (距止损${distancePercent}%)`;
}
} else if (latestTrade.action === "卖出") {
stopLossPrice = tradePrice * (1 + CONFIG.STOP_LOSS_PERCENT / 100);
stopLossDisplay = `$${stopLossPrice.toFixed(2)} (涨${CONFIG.STOP_LOSS_PERCENT}%)`;
if (currentPrice >= stopLossPrice) {
statusDisplay = "🚨 触发踏空止损";
} else {
const distancePercent = ((stopLossPrice - currentPrice) / currentPrice * 100).toFixed(2);
statusDisplay = `✅ 安全 (距止损${distancePercent}%)`;
}
}
stopLossTable.rows.push([
latestTrade.action === "买入" ? "📈 买入" : "📉 卖出",
coin,
`$${tradePrice.toFixed(2)}`,
`$${currentPrice.toFixed(2)}`,
priceChangeDisplay,
stopLossDisplay,
statusDisplay
]);
}
} catch (e) {
Log(`❌ 创建止损表失败: ${e.message}`);
stopLossTable.rows.push(["-", "-", "-", "-", "-", "-", e.message]);
}
return stopLossTable;
}
// ========== 显示仪表板 ==========
function displayDashboard() {
try {
const equityTable = createEquityTable();
const stopLossTable = createStopLossTable();
const signalTable = createSignalTable();
const tradeTable = createTradeRecordsTable();
const dashboardDisplay =
'`' + JSON.stringify(equityTable) + '`\n\n' +
'`' + JSON.stringify(stopLossTable) + '`\n\n' +
'`' + JSON.stringify(signalTable) + '`\n\n' +
'`' + JSON.stringify(tradeTable) + '`';
LogStatus(dashboardDisplay);
} catch (e) {
Log(`❌ 显示仪表板失败: ${e.message}`);
LogStatus('❌ 仪表板显示失败: ' + e.message);
}
}
// ========== 主函数 ==========
function main() {
initialize();
Log("🚀 现货自动交易机器人启动");
Log(`⚙️ 配置: 交易量=${CONFIG.TRADE_AMOUNT}, 止损比例=${CONFIG.STOP_LOSS_PERCENT}%`);
Log(`📡 监听频道: ${CONFIG.UUID}`);
while (true) {
try {
// 1. 检查止损(优先级最高)
const stopLossInfo = checkStopLoss();
if (stopLossInfo.triggered) {
const stopLossExecuted = executeStopLoss(stopLossInfo);
if (stopLossExecuted) {
Log(`🛡️ 止损执行成功: ${stopLossInfo.action} ${stopLossInfo.coin}`);
}
}
// 2. 获取并处理AI信号
const signal = receiveSignal();
if (signal) {
const result = processSignal(signal);
if (result.executed) {
Log(`✅ ${result.coin} 交易执行: ${result.action} - ${result.reason}`);
}
}
// 3. 显示仪表板
displayDashboard();
// 4. 等待
Sleep(CONFIG.CHECK_INTERVAL);
} catch (e) {
Log(`❌ 主循环异常: ${e.message}`);
Sleep(5000);
}
}
}