Polymarket AI 预测市场交易策略


创建日期: 2026-02-14 12:15:30 最后修改: 2026-02-26 12:49:53
复制: 8 点击次数: 122
avatar of Zero Zero
6
关注
918
关注者

🤖 AI驱动的Polymarket预测市场交易策略

让人工智能帮你在预测市场中捕捉机会


想象一下:川普会赢得2024大选吗?比特币能突破10万美元吗?下一任美联储主席是谁?

这些问题不再只是茶余饭后的谈资——在Polymarket上,它们都是可以真金白银交易的市场。而现在,你可以让AI帮你分析、搜索最新新闻、做出交易决策。


🎯 这个策略能做什么?

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   扫描热门市场   │ ──▶ │  AI生成搜索词    │ ──▶ │   联网搜索新闻   │
└─────────────────┘     └─────────────────┘     └─────────────────┘
                                                         │
                                                         ▼
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│    自动下单      │ ◀── │   AI交易决策     │ ◀── │   分析搜索结果   │
└─────────────────┘     └─────────────────┘     └─────────────────┘

核心流程:

  1. 自动扫描 热门预测市场(按24小时交易量排序)
  2. AI分析 每个问题,生成精准的搜索关键词
  3. 联网搜索 最新新闻、官方声明、专家分析
  4. 智能决策 基于搜索结果判断YES或NO
  5. 自动执行 交易指令,风险可控

💡 为什么选择AI交易预测市场?

传统方式的痛点:

  • ❌ 需要自己追踪上百个市场
  • ❌ 容易错过突发新闻
  • ❌ 情绪化交易导致亏损
  • ❌ 24小时盯盘精力有限

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) | ✅ 可交易

🛠️ 快速部署指南

第一步:准备API密钥

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决策逻辑详解

让我们看看AI是如何分析一个市场的:

示例:分析”Will Bitcoin hit $100k in 2024?”

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资金持续流入,美联储降息预期升温,技术形态看涨"
}

🔒 风险控制机制

1. 自动黑名单

// AI判断某些市场无利可图时自动屏蔽
if (trade.action === "block") {
    addToBlacklist(question);
    Log("AI建议屏蔽:", trade.reason);
}

当市场价格已接近0或1(概率极端),AI会自动将其加入黑名单,避免无意义交易。

2. 仓位管理

// 基于权益百分比计算交易量
var tradeAmount = Math.min(
    g_accountState.equity * (POSITION_SIZE_PERCENT / 100),
    MAX_TRADE_AMOUNT,
    availableBalance
);

永远不会单笔投入过多资金,保护本金安全。

3. 对冲保护

// 同一问题不能同时持有YES和NO
if (posBase === symbolBase && posSymbol !== symbol) {
    oppositeHeld = true;
    Log("已持有相反方向:", posSymbol);
}

防止自相矛盾的交易,避免两头亏损。


📈 实战案例

案例1:捕捉美联储决议机会

背景: 市场”Fed rate cut in September?“价格为65% YES

AI分析流程: 1. 搜索”Federal Reserve September meeting rate decision” 2. 发现多家投行预测降息概率达80% 3. 判断市场定价偏低,存在机会 4. 买入YES,目标获利15%

案例2:规避体育赛事风险

背景: NBA总决赛市场交易活跃

自定义提示词: “避免体育赛事”

AI响应:

{
  "action": "skip",
  "reason": "用户偏好排除体育市场"
}

🚀 进阶玩法

1. 多模型对比

尝试不同的AI模型,观察决策差异: - gpt-4o — 综合能力强 - claude-3-opus — 推理细致 - deepseek-v3 — 成本更低

2. 自定义市场筛选

修改代码添加筛选条件:

// 只分析流动性大于50K的市场
if (info.liquidityNum < 50000) continue;

// 只分析30天内结束的市场
var daysToEnd = (new Date(info.endDate) - new Date()) / 86400000;
if (daysToEnd > 30) continue;

3. 组合策略

同时运行多个实例,覆盖不同领域: - 实例A:政治类市场 - 实例B:科技/加密类 - 实例C:体育赛事


⚠️ 风险提示

  1. 预测市场有归零风险 — 单一市场可能完全亏损
  2. AI并非万能 — 突发事件可能导致判断失误
  3. API调用有成本 — 每次分析消耗OpenAI和Brave额度
  4. 过去表现不代表未来 — 市场环境持续变化

建议: 小额试跑,充分理解策略后再逐步加仓。


💬 常见问题

Q: 为什么我的AI没有交易? A: 可能是AI判断当前市场无明确机会,或账户余额不足。查看日志中的”跳过”原因。

Q: 如何提高交易频率? A: 降低AI交易周期参数,或在自定义提示词中要求”更激进的交易风格”。

Q: 支持哪些AI接口? A: 任何兼容OpenAI Chat Completion格式的接口,包括Azure、Anthropic、本地LLM等。


🎉 立即开始

  1. 复制策略代码
  2. 配置API密钥
  3. 设置交易参数
  4. 启动策略,让AI开始工作!

预测未来的最好方式,就是参与创造它。


策略仅供学习交流,投资有风险,入市需谨慎。

策略源码
// 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);
    }
}