想象一下:川普会赢得2024大选吗?比特币能突破10万美元吗?下一任美联储主席是谁?
这些问题不再只是茶余饭后的谈资——在Polymarket上,它们都是可以真金白银交易的市场。而现在,你可以让AI帮你分析、搜索最新新闻、做出交易决策。
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 扫描热门市场 │ ──▶ │ AI生成搜索词 │ ──▶ │ 联网搜索新闻 │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 自动下单 │ ◀── │ AI交易决策 │ ◀── │ 分析搜索结果 │
└─────────────────┘ └─────────────────┘ └─────────────────┘
核心流程:
📊 热门市场 Top 100 | 当前持仓: 3
┌────┬─────────────────────────────────┬───────┬───────┬─────────┬────────┬─────────┬────────────┬──────────────┬────────┐
│ # │ 问题 │ Yes% │ No% │ 24h变动 │ 24h量 │ 流动性 │ 结束日期 │ 持仓 │ 浮盈 │
├────┼─────────────────────────────────┼───────┼───────┼─────────┼────────┼─────────┼────────────┼──────────────┼────────┤
│ 1 │ Will Trump win 2024 election? │ 52.3 │ 47.7 │ +2.15% │ $1.2M │ $850K │ 2024-11-05 │ YES 50 USDC │ +3.25 │
│ 2 │ BTC above $100k by Dec 2024? │ 38.5 │ 61.5 │ -1.20% │ $980K │ $720K │ 2024-12-31 │ NO 30 USDC │ +1.80 │
│ 3 │ Fed rate cut in September? │ 65.2 │ 34.8 │ +5.50% │ $750K │ $500K │ 2024-09-18 │ - │ - │
└────┴─────────────────────────────────┴───────┴───────┴─────────┴────────┴─────────┴────────────┴──────────────┴────────┘
💰 权益: 1,250.00 USDC | 可用: 1,170.00 USDC | 持仓: 3个 (80.00 USDC) | ✅ 可交易
1. OpenAI API Key(或其他兼容接口) - 访问 platform.openai.com - 创建API Key,建议使用GPT-4o模型
2. Brave Search API Key - 访问 brave.com/search/api - 免费套餐每月2000次搜索,足够使用
| 参数 | 建议值 | 说明 |
|---|---|---|
| AI交易周期 | 60分钟 | 每小时分析一次,平衡效率与API成本 |
| 仓位比例 | 5% | 保守起见,每笔交易占权益5% |
| 单笔最大金额 | 100 USDC | 控制单笔风险 |
| 最大持仓数 | 5 | 分散投资,不把鸡蛋放一个篮子 |
在自定义提示词中输入你的偏好:
专注于美国政治类市场。
避免体育赛事和加密货币价格预测。
风格偏保守,只有置信度非常高时才交易。
优先选择结束日期在30天内的短期市场。
让我们看看AI是如何分析一个市场的:
Step 1: AI生成搜索词
{
"queries": [
"Bitcoin price prediction 2024 analyst forecast",
"BTC ETF inflows latest news",
"Federal Reserve rate decision impact crypto"
]
}
Step 2: 搜索引擎返回结果
[NEWS] BlackRock Bitcoin ETF sees record $500M inflow - Bloomberg
[NEWS] Fed signals potential rate cut in Q4 - Reuters
[Article] Technical analysis: BTC forming bullish cup and handle
Step 3: AI交易决策
{
"action": "buy",
"symbol": "bitcoin-100k-2024_USDC.YES",
"reason": "ETF资金持续流入,美联储降息预期升温,技术形态看涨"
}
// AI判断某些市场无利可图时自动屏蔽
if (trade.action === "block") {
addToBlacklist(question);
Log("AI建议屏蔽:", trade.reason);
}
当市场价格已接近0或1(概率极端),AI会自动将其加入黑名单,避免无意义交易。
// 基于权益百分比计算交易量
var tradeAmount = Math.min(
g_accountState.equity * (POSITION_SIZE_PERCENT / 100),
MAX_TRADE_AMOUNT,
availableBalance
);
永远不会单笔投入过多资金,保护本金安全。
// 同一问题不能同时持有YES和NO
if (posBase === symbolBase && posSymbol !== symbol) {
oppositeHeld = true;
Log("已持有相反方向:", posSymbol);
}
防止自相矛盾的交易,避免两头亏损。
背景: 市场”Fed rate cut in September?“价格为65% YES
AI分析流程: 1. 搜索”Federal Reserve September meeting rate decision” 2. 发现多家投行预测降息概率达80% 3. 判断市场定价偏低,存在机会 4. 买入YES,目标获利15%
背景: NBA总决赛市场交易活跃
自定义提示词: “避免体育赛事”
AI响应:
{
"action": "skip",
"reason": "用户偏好排除体育市场"
}
尝试不同的AI模型,观察决策差异:
- gpt-4o — 综合能力强
- claude-3-opus — 推理细致
- deepseek-v3 — 成本更低
修改代码添加筛选条件:
// 只分析流动性大于50K的市场
if (info.liquidityNum < 50000) continue;
// 只分析30天内结束的市场
var daysToEnd = (new Date(info.endDate) - new Date()) / 86400000;
if (daysToEnd > 30) continue;
同时运行多个实例,覆盖不同领域: - 实例A:政治类市场 - 实例B:科技/加密类 - 实例C:体育赛事
建议: 小额试跑,充分理解策略后再逐步加仓。
Q: 为什么我的AI没有交易? A: 可能是AI判断当前市场无明确机会,或账户余额不足。查看日志中的”跳过”原因。
Q: 如何提高交易频率?
A: 降低AI交易周期参数,或在自定义提示词中要求”更激进的交易风格”。
Q: 支持哪些AI接口? A: 任何兼容OpenAI Chat Completion格式的接口,包括Azure、Anthropic、本地LLM等。
预测未来的最好方式,就是参与创造它。
策略仅供学习交流,投资有风险,入市需谨慎。
// AI驱动的Polymarket交易策略 (重构版)
// @ts-check
var CACHE_KEY = "hotMarketsCache";
var BLACKLIST_KEY = "questionBlacklist";
var REDEEM_KEY = "redeemHistory";
var PREDICTION_HISTORY_KEY = "predictionHistory";
// ========== 工具函数 ==========
function getBlacklist() {
var list = _G(BLACKLIST_KEY) || [];
if (list.length > 0 && typeof list[0] === "string") {
list = list.map(function (q) { return { question: q, reason: "" }; });
_G(BLACKLIST_KEY, list);
}
return list;
}
function addToBlacklist(question, reason) {
if (!question) return;
var list = getBlacklist();
for (var i = 0; i < list.length; i++) {
if (list[i].question === question) return;
}
list.push({ question: question, reason: reason || "" });
_G(BLACKLIST_KEY, list);
Log("已加入黑名单:", question.substring(0, 80));
}
function removeFromBlacklist(question) {
var list = getBlacklist().filter(function (x) { return x.question !== question; });
_G(BLACKLIST_KEY, list);
}
function extractJSON(text) {
var m = text.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
if (m) try { return JSON.parse(m[1]); } catch (e) { }
var depth = 0, start = -1;
for (var i = 0; i < text.length; i++) {
if (text[i] === '{') { if (depth === 0) start = i; depth++; }
else if (text[i] === '}') {
depth--; if (depth === 0 && start !== -1) {
try { return JSON.parse(text.substring(start, i + 1)); } catch (e) { start = -1; }
}
}
}
return null;
}
function callAI(prompt, system) {
if (CUSTOM_PROMPT) system += "\n\n## 用户规则\n" + CUSTOM_PROMPT;
var url = AI_BASE_URL.replace(/\/$/, "") + "/v1/chat/completions";
// 检测是否是思考模型
var isReasoningModel = AI_MODEL.indexOf("reasoner") !== -1 ||
AI_MODEL.indexOf("think") !== -1 ||
AI_MODEL.indexOf("o1") !== -1 ||
AI_MODEL.indexOf("o3") !== -1;
var requestBody = {
model: AI_MODEL,
messages: [{ role: "system", content: system }, { role: "user", content: prompt }],
temperature: 0.7
};
// 思考模型通常不支持 temperature 参数,或者需要特殊处理
if (isReasoningModel) {
delete requestBody.temperature;
}
//Log("AI Ask:", prompt)
var ret = HttpQuery(url, {
method: "POST",
headers: { "Content-Type": "application/json", "Authorization": "Bearer " + AI_API_KEY },
body: JSON.stringify(requestBody),
timeout: 60000 * 10
});
if (!ret) return null;
try {
var parsed = JSON.parse(ret);
var message = parsed.choices[0].message;
var content = message.content;
// 如果是思考模型且有推理内容,可以选择记录
if (isReasoningModel && message.reasoning_content) {
//Log("AI推理过程:", message.reasoning_content.substring(0, 500) + "...");
}
//Log("AI Response: ", content)
return content;
} catch (e) { return null; }
}
function webSearch(query) {
var ret = HttpQuery("https://api.search.brave.com/res/v1/web/search?q=" + encodeURIComponent(query) + "&count=10", {
headers: { "Accept": "application/json", "X-Subscription-Token": BRAVE_API_KEY },
timeout: 30000
});
if (!ret) return [];
try {
var obj = JSON.parse(ret), results = [];
if (obj.web && obj.web.results) {
obj.web.results.forEach(function (r) {
results.push({ title: r.title, url: r.url, description: r.description, age: r.age || "" });
});
}
if (obj.news && obj.news.results) {
obj.news.results.forEach(function (n) {
results.push({ title: "[NEWS] " + n.title, url: n.url, description: n.description, age: n.age || "" });
});
}
return results;
} catch (e) { return []; }
}
function fmt(num) {
if (num >= 1e6) return (num / 1e6).toFixed(2) + "M";
if (num >= 1e3) return (num / 1e3).toFixed(2) + "K";
return num.toFixed(2);
}
// ========== 账户与持仓 ==========
function getAccountState() {
var acc = exchange.GetAccount();
if (!acc) return null;
var positions = exchange.GetPositions() || [];
var posValue = 0;
positions.forEach(function (p) {
posValue += p.Amount || 0;
});
var equity = acc.Equity;
var canTrade = true, stopReason = "";
if (acc.Balance < MIN_BALANCE_TO_TRADE) {
canTrade = false;
stopReason = "余额不足(" + acc.Balance.toFixed(2) + "<" + MIN_BALANCE_TO_TRADE + ")";
} else if (positions.length >= MAX_POSITIONS) {
canTrade = false;
stopReason = "持仓已满(" + positions.length + "/" + MAX_POSITIONS + ")";
}
return { equity: equity, balance: acc.Balance, frozenBalance: acc.FrozenBalance, positionCount: positions.length, positionValue: posValue, canTrade: canTrade, stopReason: stopReason, positions: positions };
}
function checkRedeem() {
var positions = exchange.GetPositions() || [];
var count = 0;
positions.forEach(function (p) {
if (p.Info && p.Info.redeemable) {
Log("Redeem:", p.Symbol);
var history = _G(REDEEM_KEY) || [];
history.push({ symbol: p.Symbol, eventSlug: p.Info.eventSlug || "", amount: p.Amount, profit: p.Profit, time: new Date().getTime() });
_G(REDEEM_KEY, history);
exchange.IO("redeem", p.Symbol, true);
count++;
}
});
if (count > 0) Sleep(3000);
return count;
}
// ========== 市场数据 ==========
function getHotMarkets() {
var markets = exchange.GetMarkets();
if (!markets) return [];
var now = new Date().getTime();
var blacklist = getBlacklist();
var blackSet = {};
blacklist.forEach(function (b) { blackSet[b.question] = true; });
var filterKw = FILTER_KEYWORDS ? FILTER_KEYWORDS.toLowerCase().split(",").map(function (s) { return s.trim(); }).filter(Boolean) : [];
var positions = exchange.GetPositions() || [];
var posQuestions = {};
positions.forEach(function (p) {
if (markets[p.Symbol] && markets[p.Symbol].Info) {
posQuestions[markets[p.Symbol].Info.question || ""] = true;
}
});
var questionMap = {};
var total = 0;
for (var sym in markets) {
total += 1;
var m = markets[sym];
// 检查是否有 outcome 信息(任何配对市场都应有)
if (!m.Info || typeof m.Info.volume24hr !== "number"/* || m.Info.feesEnabled*/) continue;
// 从 symbol 中提取 base 和 outcome
// 格式可能是: MARKET_USDC.Yes, MARKET_USDC.No, MARKET_USDC.Up, MARKET_USDC.Down 等
var lastDot = sym.lastIndexOf(".");
if (lastDot === -1) continue;
var symBase = sym.substring(0, lastDot);
var outcome = sym.substring(lastDot + 1);
if (!outcome) continue;
var q = m.Info.question || "";
var hasPos = posQuestions[q] || false;
if (!hasPos) {
if (blackSet[q]) continue;
var qLower = q.toLowerCase();
if (filterKw.some(function (kw) { return qLower.indexOf(kw) !== -1; })) continue;
if (END_DAYS_LIMIT > 0 && m.Info.endDate) {
var days = (new Date(m.Info.endDate).getTime() - now) / 86400000;
if (days < 0 || days > END_DAYS_LIMIT) continue;
}
var prices = JSON.parse(m.Info.outcomePrices || "[]");
var outcomes = JSON.parse(m.Info.outcomes || "[]");
var minPrice = 1;
for (var k = 0; k < outcomes.length; k++) {
var p = parseFloat(prices[k] || 0);
if (p < minPrice) minPrice = p;
}
if (minPrice < MIN_ODDS_THRESHOLD / 100) continue;
}
if (!questionMap[q]) {
questionMap[q] = { question: q, symbols: [], outcomes: [], mkt: m, volume: 0, hasPos: hasPos, symBase: symBase };
}
questionMap[q].volume += m.Info.volume24hr || 0;
questionMap[q].hasPos = questionMap[q].hasPos || hasPos;
questionMap[q].symbols.push(sym);
questionMap[q].outcomes.push(outcome);
questionMap[q].mkt = m;
}
var list = [];
for (var qq in questionMap) {
var item = questionMap[qq];
// 只要有两个或以上的 outcome 就可以交易
if (item.symbols.length >= 2) {
// 为了兼容性,设置 symbol1 和 symbol2(取前两个)
item.symbol1 = item.symbols[0];
item.symbol2 = item.symbols[1];
item.outcome1 = item.outcomes[0];
item.outcome2 = item.outcomes[1];
list.push(item);
}
}
list.sort(function (a, b) { return b.volume - a.volume; });
var posMarkets = list.filter(function (x) { return x.hasPos; });
var otherMarkets = list.filter(function (x) { return !x.hasPos; });
var result = posMarkets.concat(otherMarkets.slice(0, Math.max(0, TOP_N - posMarkets.length)));
var cache = _G(CACHE_KEY) || {};
_G(CACHE_KEY, { data: result, time: now, aiCounts: cache.aiCounts || {}, aiReasons: cache.aiReasons || {} });
Log("热门市场:", result.length, "个", "全部市场共", total, " (持仓:", posMarkets.length, ")");
return result;
}
// ========== AI交易逻辑 ==========
function getPredictionHistory(question) {
var history = _G(PREDICTION_HISTORY_KEY) || {};
return history[question] || null;
}
function savePredictionHistory(question, prediction, price1, price2, outcome1, outcome2) {
var history = _G(PREDICTION_HISTORY_KEY) || {};
history[question] = {
time: new Date().getTime(),
action: prediction.action,
symbol: prediction.symbol,
confidence: prediction.confidence || 0,
estimatedProb: prediction.estimatedProb || "",
reason: prediction.reason || "",
marketPrice1: price1,
marketPrice2: price2,
outcome1: outcome1 || "Option1",
outcome2: outcome2 || "Option2"
};
// 只保留最近200条记录,避免存储过大
var keys = Object.keys(history);
if (keys.length > 200) {
var sorted = keys.map(function (k) { return { k: k, t: history[k].time }; })
.sort(function (a, b) { return b.t - a.t; });
var keep = {};
for (var i = 0; i < 200; i++) {
keep[sorted[i].k] = history[sorted[i].k];
}
history = keep;
}
_G(PREDICTION_HISTORY_KEY, history);
}
function analyzeQuestion(item, positions) {
var q = item.question;
var symbol1 = item.symbol1, symbol2 = item.symbol2;
var outcome1 = item.outcome1, outcome2 = item.outcome2;
var info = item.mkt.Info;
var prices = JSON.parse(info.outcomePrices || "[]");
var outcomes = JSON.parse(info.outcomes || "[]");
var price1 = 0, price2 = 0;
for (var i = 0; i < outcomes.length; i++) {
if (outcomes[i] === outcome1) price1 = parseFloat(prices[i] || 0);
if (outcomes[i] === outcome2) price2 = parseFloat(prices[i] || 0);
}
var existingPos = null;
var symBase = item.symBase;
for (var p = 0; p < positions.length; p++) {
var posSym = positions[p].Symbol;
var posBase = posSym.substring(0, posSym.lastIndexOf("."));
if (posBase === symBase && positions[p].Amount > 0) {
existingPos = positions[p];
break;
}
}
// 获取ticker
var ticker1 = exchange.GetTicker(symbol1);
var ticker2 = exchange.GetTicker(symbol2);
Sleep(100);
// 计算买卖价差
var spread1 = ticker1 ? ((ticker1.Sell - ticker1.Buy) / ticker1.Buy * 100).toFixed(2) : "N/A";
var spread2 = ticker2 ? ((ticker2.Sell - ticker2.Buy) / ticker2.Buy * 100).toFixed(2) : "N/A";
// 计算距离结束时间
var now = new Date().getTime();
var daysLeft = info.endDate ? ((new Date(info.endDate).getTime() - now) / 86400000).toFixed(1) : "未知";
// 获取上次预测历史
var lastPrediction = getPredictionHistory(q);
var historyInfo = "";
if (lastPrediction) {
var timeSince = ((now - lastPrediction.time) / 3600000).toFixed(1); // 小时
var price1Change = Number(((price1 - lastPrediction.marketPrice1) * 100).toFixed(2));
var price2Change = Number(((price2 - lastPrediction.marketPrice2) * 100).toFixed(2));
historyInfo = "\n\n=== 你的上次预测 (" + timeSince + "小时前) ===\n" +
"决策: " + lastPrediction.action + " " + lastPrediction.symbol + "\n" +
"置信度: " + lastPrediction.confidence + "%\n" +
"估计概率: " + lastPrediction.estimatedProb + "\n" +
"理由: " + lastPrediction.reason + "\n" +
"当时市场价格: " + lastPrediction.outcome1 + "=" + (lastPrediction.marketPrice1 * 100).toFixed(1) + "%, " + lastPrediction.outcome2 + "=" + (lastPrediction.marketPrice2 * 100).toFixed(1) + "%\n" +
"价格变化: " + lastPrediction.outcome1 + " " + (price1Change >= 0 ? "+" : "") + price1Change + "%, " + lastPrediction.outcome2 + " " + (price2Change >= 0 ? "+" : "") + price2Change + "%";
}
var marketInfo = "=== 市场信息 ===\n" +
"问题: " + q + "\n" +
"描述: " + (info.description || "无描述") + "\n" +
"结束时间: " + (info.endDate || "未知") + " (剩余" + daysLeft + "天)\n" +
"24h交易量: $" + (info.volume24hr || 0).toFixed(0) + "\n\n" +
outcome1 + "(" + symbol1 + "): 当前概率" + (price1 * 100).toFixed(1) + "%" +
(ticker1 ? " | 买价(bid)=" + ticker1.Buy.toFixed(3) + " 卖价(ask)=" + ticker1.Sell.toFixed(3) + " 价差=" + spread1 + "%" : "") + "\n" +
outcome2 + "(" + symbol2 + "): 当前概率" + (price2 * 100).toFixed(1) + "%" +
(ticker2 ? " | 买价(bid)=" + ticker2.Buy.toFixed(3) + " 卖价(ask)=" + ticker2.Sell.toFixed(3) + " 价差=" + spread2 + "%" : "") +
historyInfo;
// Step 1: 生成搜索词
var searchResp = callAI(
marketInfo + "\n\n请生成2-3个精准的英文搜索关键词,用于获取能判断该事件结果的最新新闻和信息。\n" +
"要求:\n" +
"1. 关键词必须能找到最近24-48小时内的相关新闻\n" +
"2. 包含具体人名、事件名、时间点等具体信息\n" +
"3. 优先搜索官方声明、权威媒体报道、实时数据\n\n" +
"返回JSON: {\"queries\": [\"...\", \"...\"]}",
"你是专业的信息检索专家,擅长构造能找到最新、最相关信息的搜索词。"
);
var queries = [];
if (searchResp) {
var obj = extractJSON(searchResp);
if (obj && obj.queries) queries = obj.queries;
}
if (queries.length === 0) return null;
Log("搜索:", queries.join(", "));
// Step 2: 执行搜索
var searchResults = [];
for (var s = 0; s < queries.length && s < 3; s++) {
searchResults.push({ query: queries[s], results: webSearch(queries[s]) });
Sleep(1000);
}
// Step 3: 交易建议
var tradingSystem = "你是一个极其谨慎、纪律严明的预测市场专业交易员。\n\n" +
"## 核心原则\n" +
"1. **只在有明确信息优势时交易** - 如果搜索结果没有提供市场尚未反映的新信息,必须skip\n" +
"2. **概率错误定价优先** - 只在你判断的真实概率与市场价格相差>15%时才考虑交易\n" +
"3. **避免50:50博弈** - 如果事件结果高度不确定,宁可不参与\n" +
"4. **时间价值** - 距离结束越近,需要的信息优势越大\n" +
"5. **流动性风险** - 价差>5%的市场不参与\n\n" +
"## 必须skip的情况\n" +
"- 搜索结果中没有24小时内的相关新闻\n" +
"- 信息模糊、互相矛盾或来源不可靠\n" +
"- 事件结果取决于不可预测因素(如选举投票、随机事件)\n" +
"- 市场已经正确定价(价格已反映最新信息)\n" +
"- 你的信心度<70%\n\n" +
"## 必须block的情况(永久屏蔽)\n" +
"- 市场问题表述模糊、有多种解读\n" +
"- 结算规则不清晰\n" +
"- 纯粹的赌博性质市场(如体育比分、随机抽奖)\n";
// 如果有历史预测,添加反思提示
if (lastPrediction) {
tradingSystem += "\n## 历史预测反思\n" +
"你会看到自己上次对这个市场的预测。请:\n" +
"1. 反思上次预测是否准确(价格变化是否符合预期)\n" +
"2. 分析上次判断的逻辑是否依然成立\n" +
"3. 如果市场走势与预测相反,思考是否需要修正观点\n" +
"4. 避免固执己见——新信息应该更新你的判断\n";
}
var tradePrompt;
if (existingPos) {
var posOutcome = existingPos.Symbol.substring(existingPos.Symbol.lastIndexOf(".") + 1);
var profitPct = existingPos.Price > 0 ? ((existingPos.Profit / (existingPos.Price * existingPos.Amount)) * 100).toFixed(2) : "0";
tradePrompt = marketInfo + "\n\n当前持仓:\n" +
"方向: " + posOutcome + "\n" +
"数量: " + existingPos.Amount.toFixed(2) + " USDC\n" +
"入场价: " + existingPos.Price.toFixed(4) + "\n" +
"当前浮盈: " + existingPos.Profit.toFixed(4) + " (" + profitPct + "%)\n\n" +
"=== 搜索结果 ===\n" + JSON.stringify(searchResults, null, 2) + "\n\n" +
"## 持仓评估任务\n" +
"基于最新信息,判断是否应该平仓:\n\n" +
"**卖出信号(sell)**:\n" +
"- 新信息表明你的方向判断错误\n" +
"- 概率已大幅向不利方向移动且趋势确立\n" +
"- 原本的信息优势已消失(市场已充分定价)\n" +
"- 止损: 浮亏超过20%且无反转迹象\n\n" +
"**继续持有信号(skip)**:\n" +
"- 原有判断逻辑依然成立\n" +
"- 新信息支持你的方向\n" +
"- 等待确定性结果公布\n\n" +
"返回JSON: {\"action\": \"sell|skip\", \"symbol\": \"" + existingPos.Symbol + "\", \"confidence\": 70-100, \"reason\": \"简要说明\"}";
} else {
tradePrompt = marketInfo + "\n\n搜索结果:\n" + JSON.stringify(searchResults, null, 2) + "\n\n" +
"## 交易决策任务\n" +
"基于以上信息,判断是否存在交易机会:\n\n" +
"**分析步骤**:\n" +
"1. 搜索结果中有没有最新(24h内)的关键信息?\n" +
"2. 这些信息是否已被市场价格反映?\n" +
"3. 你判断的真实概率是多少?与市场价格差异多大?\n" +
"4. 你的信心度有多高(0-100)?\n\n" +
"**决策**:\n" +
"- buy: 只在信心度>=75%且概率错配>=15%时买入\n" +
"- skip: 信息不足或没有明显优势\n" +
"- block: 市场本身有问题,永久屏蔽\n\n" +
"返回JSON: {\n" +
" \"action\": \"buy|skip|block\",\n" +
" \"symbol\": \"" + symbol1 + "或" + symbol2 + "\",\n" +
" \"confidence\": 0-100,\n" +
" \"estimatedProb\": \"你估计的真实概率%\",\n" +
" \"reason\": \"简要说明判断依据\"\n" +
"}";
}
var tradeResp = callAI(tradePrompt, tradingSystem);
if (!tradeResp) return null;
var trade = extractJSON(tradeResp);
// 保存AI建议
var cache = _G(CACHE_KEY) || { data: [], time: 0, aiCounts: {}, aiReasons: {} };
cache.aiCounts[q] = (cache.aiCounts[q] || 0) + 1;
cache.aiReasons[q] = trade ? (trade.action + "[" + (trade.confidence || "?") + "%]: " + (trade.reason || "")) : "无建议";
_G(CACHE_KEY, cache);
if (!trade || !trade.action || trade.action === "skip" || trade.action === "none") return null;
// 保存本次预测到历史(无论是否执行交易)
savePredictionHistory(q, trade, price1, price2, outcome1, outcome2);
// 信心度检查
if (trade.action === "buy" && trade.confidence && trade.confidence < 75) {
Log("信心度不足:", trade.confidence, "% <75%, 跳过");
return null;
}
if (trade.action === "block") {
addToBlacklist(q, trade.reason || "");
return null;
}
// 验证symbol
if (trade.symbol !== symbol1 && trade.symbol !== symbol2) {
Log("无效symbol:", trade.symbol);
return null;
}
return { action: trade.action, symbol: trade.symbol, reason: trade.reason, existingPos: existingPos };
}
function executeTrade(trade, accState) {
if (!trade || !accState.canTrade) return false;
var symbol = trade.symbol, action = trade.action;
// 防止加仓
if (action === "buy" && trade.existingPos) {
Log("禁止加仓:", symbol);
return false;
}
var orderSide, orderAmount;
if (action === "buy") {
var amt = Math.min(accState.equity * POSITION_SIZE_PERCENT / 100, MAX_TRADE_AMOUNT, accState.balance);
amt = _N(amt, 2);
if (amt < 5) {
Log("金额过小:", amt);
return false;
}
orderSide = "buy";
orderAmount = amt;
} else if (action === "sell" && trade.existingPos) {
orderSide = "closebuy";
orderAmount = trade.existingPos.Amount;
} else {
return false;
}
Log("交易:", symbol, orderSide, orderAmount, "USDC |", trade.reason || "");
var orderId = exchange.CreateOrder(symbol, orderSide, -1, _N(orderAmount, 2));
if (orderId) {
Log("成功:", orderId);
return true;
} else {
Log("失败:", GetLastError());
return false;
}
}
// ========== 状态栏 ==========
function updateStatus() {
var cache = _G(CACHE_KEY);
if (!cache || !cache.data) return;
var accState = getAccountState();
if (!accState) return;
var hotList = cache.data;
var positions = accState.positions;
var now = new Date().getTime();
var rows = [];
for (var i = 0; i < hotList.length; i++) {
var m = hotList[i];
var info = m.mkt.Info;
var prices = JSON.parse(info.outcomePrices || "[]");
var outcomes = JSON.parse(info.outcomes || "[]");
// 构建所有 outcome 的价格显示
var outcomePrices = [];
for (var j = 0; j < outcomes.length && j < prices.length; j++) {
var pr = (parseFloat(prices[j] || 0) * 100).toFixed(1);
outcomePrices.push(outcomes[j] + ":" + pr);
}
var priceDisplay1 = outcomePrices[0] || "-";
var priceDisplay2 = outcomePrices[1] || "-";
var daysLeft = "";
if (info.endDate) {
var days = (new Date(info.endDate).getTime() - now) / 86400000;
daysLeft = days < 0 ? "结束" : (days < 1 ? (days * 24).toFixed(1) + "h" : days.toFixed(1) + "d");
}
var pos = positions.find(function (p) { return p.Symbol === m.symbol1 || p.Symbol === m.symbol2; });
var posStr = pos ? (pos.Symbol.substring(pos.Symbol.lastIndexOf(".") + 1) + " " + pos.Amount.toFixed(2)) : "";
var profitStr = pos ? pos.Profit.toFixed(4) : "";
var priceStr = pos ? pos.Price.toFixed(4) : "";
var aiCount = cache.aiCounts[info.question] || 0;
var aiReason = (cache.aiReasons[info.question] || "-").substring(0, 50);
var q = (info.question || "").substring(0, 150);
var ops: any = "-";
if (pos) {
ops = [{ type: "button", cmd: "CLOSE:" + pos.Symbol, name: "平仓" }, { type: "button", cmd: "BLOCK:" + encodeURIComponent(info.question), name: "屏蔽" }];
}
rows.push([i + 1, q, aiCount, priceDisplay1, priceDisplay2, "$" + fmt(info.volume24hr || 0), daysLeft, posStr, priceStr, profitStr, aiReason, ops]);
}
var table = { type: "table", title: "热门市场 Top" + hotList.length + " | 持仓:" + positions.length, cols: ["#", "问题", "AI", "选项1", "选项2", "24h量", "剩余", "持仓", "均价", "浮盈", "AI建议", "操作"], rows: rows };
var blacklist = getBlacklist();
var tables = [table];
if (blacklist.length > 0) {
var bRows = blacklist.map(function (b, idx) {
return [idx + 1, b.question.substring(0, 100), b.reason.substring(0, 50), { type: "button", cmd: "UNBLOCK:" + encodeURIComponent(b.question), name: "移除" }];
});
tables.push({ type: "table", title: "黑名单(" + blacklist.length + ")", cols: ["#", "问题", "原因", "操作"], rows: bRows });
}
var redeemHistory = _G(REDEEM_KEY) || [];
if (redeemHistory.length > 0) {
var rRows = redeemHistory.slice().sort(function (a, b) { return b.time - a.time; }).slice(0, 20).map(function (r, idx) {
return [idx + 1, _D(r.time), r.symbol, r.amount.toFixed(2), r.profit.toFixed(4)];
});
tables.push({ type: "table", title: "Redeem历史(" + redeemHistory.length + ")", cols: ["#", "时间", "Symbol", "数量", "盈亏"], rows: rRows });
}
var statusLine = "💰权益:" + accState.equity.toFixed(2) + " 可用:" + accState.balance.toFixed(2) + " 持仓:" + accState.positionCount + "个 " + (accState.canTrade ? "✅可交易" : "⛔" + accState.stopReason) + " | " + _D();
LogStatus("`" + JSON.stringify(tables) + "`\n" + statusLine);
}
// ========== 命令处理 ==========
function handleCommand() {
var cmd = GetCommand();
if (!cmd) {
return
}
Log("命令:", cmd);
if (cmd === "CLOSE_ALL") {
var positions = exchange.GetPositions() || [];
positions.forEach(function (p) {
if (p.Amount > 0) exchange.CreateOrder(p.Symbol, "closebuy", -1, p.Amount);
});
} else if (cmd === "CLEAR_BLACKLIST") {
_G(BLACKLIST_KEY, []);
Log("黑名单已清空");
} else if (cmd === "CLEAR_LOG") {
LogReset();
} else if (cmd.indexOf("CLOSE:") === 0) {
var sym = cmd.split(":")[1];
var pos = (exchange.GetPositions() || []).find(function (p) { return p.Symbol === sym; });
if (pos && pos.Amount > 0) exchange.CreateOrder(sym, "closebuy", -1, pos.Amount);
} else if (cmd.indexOf("BLOCK:") === 0) {
addToBlacklist(decodeURIComponent(cmd.split(":")[1] || ""), "手动屏蔽");
} else if (cmd.indexOf("UNBLOCK:") === 0) {
removeFromBlacklist(decodeURIComponent(cmd.split(":")[1] || ""));
}
}
// ========== 主循环 ==========
function aiTradingCycle() {
let executed = checkRedeem();
var accState = getAccountState();
if (!accState) return;
if (!accState.canTrade) {
Log("暂停交易:", accState.stopReason);
return;
}
Log("正在加载市场...")
var markets = getHotMarkets();
if (markets.length === 0) return;
Log("开始分析", markets.length, "个市场...");
for (var i = 0; i < markets.length; i++) {
Log("===", i + 1, "/", markets.length, "===", markets[i].question.substring(0, 80));
var trade = analyzeQuestion(markets[i], accState.positions);
if (trade && executeTrade(trade, accState)) {
executed++;
accState = getAccountState(); // 刷新账户状态
if (!accState || !accState.canTrade) break;
}
Sleep(2000);
}
Log("完成,执行", executed, "笔交易");
if (accState.positionCount > 0 || executed > 0) {
LogProfit(accState.equity, "持仓:" + accState.positionCount);
}
}
function main() {
LogReset();
LogProfitReset();
//_G(null)
LogStatus("ready")
Log("策略启动 | AI:", AI_MODEL, "| 仓位:", POSITION_SIZE_PERCENT, "% | 最大:", MAX_TRADE_AMOUNT);
if (!AI_API_KEY) throw "请配置AI_API_KEY";
if (!BRAVE_API_KEY) throw "请配置BRAVE_API_KEY";
// 测试AI
var test = callAI("回复OK", "简短回复");
if (!test) throw "AI连接失败";
Log("AI连接正常");
var lastTrade = 0;
var interval = AI_TRADE_INTERVAL * 60 * 1000;
while (true) {
updateStatus()
var now = new Date().getTime();
if (now - lastTrade >= interval) {
aiTradingCycle();
lastTrade = now;
}
handleCommand()
// 取消所有挂单
var orders = exchange.GetOrders() || [];
orders.forEach(function (o) { exchange.CancelOrder(o.Id); });
Sleep(5000);
}
}