Pharos
Log

LogStatus()

记录状态信息到状态栏,支持表格、按钮、输入框等富文本交互控件。

语法

python
LogStatus(*msgs)

参数

参数名类型必选默认值说明
*msgsany-一个或多个状态消息,支持:

返回值

说明

LogStatus() 用于在策略状态栏显示实时信息,支持多种富文本格式和交互控件。状态数据保存到 status_logs 表,可通过 QueryStatusLogs RPC 接口查询。

交互机制

状态栏按钮点击后,通过 GetCommand() 函数接收交互数据:

按钮类型返回格式示例
无参数按钮"cmd""start"
单输入框 (input)"cmd:value""buy:100"
多输入框 (group)"cmd:{json}"'order:{"price":100,"amount":1}'

按钮样式 (Bootstrap)

预定义样式

Class效果使用场景
btn btn-xs btn-default默认灰色普通操作
btn btn-xs btn-primary蓝色主要操作
btn btn-xs btn-success绿色买入/开仓
btn btn-xs btn-info浅蓝信息/刷新
btn btn-xs btn-warning橙色警告/卖出
btn btn-xs btn-danger红色危险/平仓

自定义按钮颜色

方式 1: 使用十六进制颜色码 (推荐)

通过 style 属性直接设置十六进制颜色:

python
# 单色按钮
btn_purple = {
    "type": "button",
    "cmd": "action",
    "name": "紫色按钮",
    "class": "btn btn-xs",
    "style": "background-color: #9b59b6; border-color: #8e44ad; color: white;"
}

# 深蓝色按钮
btn_navy = {
    "type": "button",
    "cmd": "action",
    "name": "深蓝按钮",
    "class": "btn btn-xs",
    "style": "background-color: #000990; border-color: #000770; color: white;"
}

# 渐变色按钮
btn_gradient = {
    "type": "button",
    "cmd": "action",
    "name": "渐变按钮",
    "class": "btn btn-xs",
    "style": "background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border: none; color: white;"
}

# 金色按钮
btn_gold = {
    "type": "button",
    "cmd": "action",
    "name": "金色",
    "class": "btn btn-xs",
    "style": "background-color: #ffd700; border-color: #daa520; color: #333;"
}

方式 2: 颜色配置类 - 统一管理

python
class ButtonColors:
    """按钮颜色配置类"""
    
    # Bootstrap 预定义颜色
    DEFAULT = "btn btn-xs btn-default"    # #777 灰色
    PRIMARY = "btn btn-xs btn-primary"    # #337ab7 蓝色
    SUCCESS = "btn btn-xs btn-success"    # #5cb85c 绿色
    INFO = "btn btn-xs btn-info"          # #5bc0de 浅蓝
    WARNING = "btn btn-xs btn-warning"    # #f0ad4e 橙色
    DANGER = "btn btn-xs btn-danger"      # #d9534f 红色
    
    # 自定义十六进制颜色
    PURPLE = ("btn btn-xs", "background-color: #9b59b6; border-color: #8e44ad; color: white;")
    NAVY = ("btn btn-xs", "background-color: #000990; border-color: #000770; color: white;")
    PINK = ("btn btn-xs", "background-color: #e91e63; border-color: #c2185b; color: white;")
    TEAL = ("btn btn-xs", "background-color: #009688; border-color: #00796b; color: white;")
    ORANGE = ("btn btn-xs", "background-color: #ff5722; border-color: #e64a19; color: white;")
    LIME = ("btn btn-xs", "background-color: #cddc39; border-color: #afb42b; color: #333;")
    CYAN = ("btn btn-xs", "background-color: #00bcd4; border-color: #0097a7; color: white;")
    AMBER = ("btn btn-xs", "background-color: #ffc107; border-color: #ffa000; color: #333;")
    
    @staticmethod
    def create_button(cmd, name, color):
        """创建按钮"""
        btn = {
            "type": "button",
            "cmd": cmd,
            "name": name
        }
        
        if isinstance(color, tuple):
            # 自定义颜色 (class, style)
            btn["class"] = color[0]
            btn["style"] = color[1]
        else:
            # Bootstrap 颜色
            btn["class"] = color
        
        return btn
    
    @staticmethod
    def custom_color(hex_color, text_color="white"):
        """
        创建自定义颜色配置
        
        Args:
            hex_color: 十六进制颜色码,如 "#000990"
            text_color: 文字颜色,默认 "white"
        
        Returns:
            (class, style) 元组
        """
        # 计算边框颜色(比背景色深 15%)
        hex_color = hex_color.lstrip('#')
        r, g, b = int(hex_color[0:2], 16), int(hex_color[2:4], 16), int(hex_color[4:6], 16)
        border_r = max(0, int(r * 0.85))
        border_g = max(0, int(g * 0.85))
        border_b = max(0, int(b * 0.85))
        border_color = f"#{border_r:02x}{border_g:02x}{border_b:02x}"
        
        style = f"background-color: #{hex_color}; border-color: {border_color}; color: {text_color};"
        return ("btn btn-xs", style)

# 使用示例
btn_buy = ButtonColors.create_button("buy", "买入", ButtonColors.SUCCESS)
btn_sell = ButtonColors.create_button("sell", "卖出", ButtonColors.WARNING)
btn_custom = ButtonColors.create_button("action", "自定义", ButtonColors.PURPLE)
btn_navy = ButtonColors.create_button("navy", "深蓝", ButtonColors.custom_color("#000990"))
btn_pink = ButtonColors.create_button("pink", "粉红", ButtonColors.custom_color("#ff1493", "white"))

方式 3: 业务场景颜色映射

python
# 交易类型颜色
TRADE_COLORS = {
    "long": ("btn btn-xs", "background-color: #00c853; border-color: #00a043; color: white;"),   # 做多-亮绿
    "short": ("btn btn-xs", "background-color: #ff1744; border-color: #d50000; color: white;"),  # 做空-鲜红
    "close_long": ("btn btn-xs", "background-color: #ff6f00; border-color: #e65100; color: white;"),  # 平多-橙
    "close_short": ("btn btn-xs", "background-color: #2979ff; border-color: #2962ff; color: white;"), # 平空-蓝
}

# 风险等级颜色
RISK_COLORS = {
    "safe": ("btn btn-xs", "background-color: #4caf50; border-color: #388e3c; color: white;"),    # 安全-绿
    "low": ("btn btn-xs", "background-color: #8bc34a; border-color: #689f38; color: white;"),     # 低风险-浅绿
    "medium": ("btn btn-xs", "background-color: #ffc107; border-color: #ffa000; color: #333;"),   # 中等-黄
    "high": ("btn btn-xs", "background-color: #ff9800; border-color: #f57c00; color: white;"),    # 高风险-橙
    "danger": ("btn btn-xs", "background-color: #f44336; border-color: #d32f2f; color: white;"),  # 危险-红
}

# 盈亏状态颜色
PROFIT_COLORS = {
    "profit_high": ("btn btn-xs", "background-color: #00e676; border-color: #00c853; color: white;"),  # 大赚
    "profit_low": ("btn btn-xs", "background-color: #76ff03; border-color: #64dd17; color: #333;"),    # 小赚
    "break_even": ("btn btn-xs", "background-color: #9e9e9e; border-color: #757575; color: white;"),   # 持平
    "loss_low": ("btn btn-xs", "background-color: #ffab00; border-color: #ff6f00; color: white;"),     # 小亏
    "loss_high": ("btn btn-xs", "background-color: #ff1744; border-color: #d50000; color: white;"),    # 大亏
}

def get_profit_button(symbol, profit):
    """根据盈亏返回不同颜色的按钮"""
    if profit > 1000:
        color_cfg = PROFIT_COLORS["profit_high"]
        text = f"平仓 +{profit:.2f}"
    elif profit > 0:
        color_cfg = PROFIT_COLORS["profit_low"]
        text = f"平仓 +{profit:.2f}"
    elif profit == 0:
        color_cfg = PROFIT_COLORS["break_even"]
        text = "平仓 ±0"
    elif profit > -500:
        color_cfg = PROFIT_COLORS["loss_low"]
        text = f"平仓 {profit:.2f}"
    else:
        color_cfg = PROFIT_COLORS["loss_high"]
        text = f"平仓 {profit:.2f}"
    
    return {
        "type": "button",
        "cmd": f"close_{symbol}",
        "name": text,
        "class": color_cfg[0],
        "style": color_cfg[1]
    }

# 使用
btn = get_profit_button("BTC", 1500)   # 大赚 - 亮绿色
btn = get_profit_button("ETH", -800)   # 大亏 - 鲜红色

方式 4: 常用颜色速查表

python
# 十六进制颜色速查字典
HEX_COLORS = {
    # 基础色
    "red": "#f44336",
    "pink": "#e91e63",
    "purple": "#9c27b0",
    "deep_purple": "#673ab7",
    "indigo": "#3f51b5",
    "blue": "#2196f3",
    "light_blue": "#03a9f4",
    "cyan": "#00bcd4",
    "teal": "#009688",
    "green": "#4caf50",
    "light_green": "#8bc34a",
    "lime": "#cddc39",
    "yellow": "#ffeb3b",
    "amber": "#ffc107",
    "orange": "#ff9800",
    "deep_orange": "#ff5722",
    "brown": "#795548",
    "grey": "#9e9e9e",
    "blue_grey": "#607d8b",
    
    # 交易专用色
    "bull_green": "#00c853",      # 牛市绿
    "bear_red": "#ff1744",        # 熊市红
    "profit_gold": "#ffd700",     # 盈利金
    "loss_crimson": "#dc143c",    # 亏损深红
    "neutral_silver": "#c0c0c0",  # 中性银
    "warning_orange": "#ff6f00",  # 警告橙
}

def create_colored_button(cmd, name, color_name):
    """使用颜色名称创建按钮"""
    hex_color = HEX_COLORS.get(color_name, "#9e9e9e")
    
    # 自动判断文字颜色(浅色背景用深色文字)
    rgb = int(hex_color.lstrip('#'), 16)
    r, g, b = (rgb >> 16) & 0xff, (rgb >> 8) & 0xff, rgb & 0xff
    luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255
    text_color = "#333" if luminance > 0.5 else "white"
    
    # 边框颜色(深 15%)
    border_r = max(0, int(r * 0.85))
    border_g = max(0, int(g * 0.85))
    border_b = max(0, int(b * 0.85))
    border_color = f"#{border_r:02x}{border_g:02x}{border_b:02x}"
    
    return {
        "type": "button",
        "cmd": cmd,
        "name": name,
        "class": "btn btn-xs",
        "style": f"background-color: {hex_color}; border-color: {border_color}; color: {text_color};"
    }

# 使用
btn_buy = create_colored_button("buy", "买入", "bull_green")
btn_sell = create_colored_button("sell", "卖出", "bear_red")
btn_custom = create_colored_button("action", "自定义", "deep_purple")

方式 5: 颜色渐变和透明度

python
# 渐变色按钮
btn_gradient_1 = {
    "type": "button",
    "cmd": "action",
    "name": "紫色渐变",
    "class": "btn btn-xs",
    "style": "background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border: none; color: white;"
}

btn_gradient_2 = {
    "type": "button",
    "cmd": "action",
    "name": "火焰渐变",
    "class": "btn btn-xs",
    "style": "background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); border: none; color: white;"
}

# 半透明按钮
btn_transparent = {
    "type": "button",
    "cmd": "action",
    "name": "半透明",
    "class": "btn btn-xs",
    "style": "background-color: rgba(0, 9, 144, 0.7); border-color: rgba(0, 9, 144, 0.9); color: white;"
}

# 发光效果
btn_glow = {
    "type": "button",
    "cmd": "action",
    "name": "发光按钮",
    "class": "btn btn-xs",
    "style": "background-color: #00ff88; border-color: #00dd77; color: #333; box-shadow: 0 0 10px #00ff88;"
}

示例

1. 纯文本状态

python
def main():
    LogStatus("策略运行中...")
    LogStatus(f"{_D()} | 当前持仓: BTC 0.5 | 盈亏: +500 USDT")

2. 基础表格

python
import json

def main():
    account = exchange.GetAccount()
    
    table = {
        "type": "table",
        "title": "账户信息",
        "cols": ["币种", "可用", "冻结", "总额"],
        "rows": [
            ["USDT", f"{account['Balance']:.2f}", f"{account['FrozenBalance']:.2f}", 
             f"{account['Balance'] + account['FrozenBalance']:.2f}"],
            ["BTC", f"{account['Stocks']:.6f}", f"{account['FrozenStocks']:.6f}", 
             f"{account['Stocks'] + account['FrozenStocks']:.6f}"]
        ]
    }
    
    LogStatus('`' + json.dumps(table) + '`')

3. 表格 - 支持颜色

python
def main():
    table = {
        "type": "table",
        "title": "持仓盈亏",
        "cols": ["币种", "数量", "成本", "现价", "盈亏"],
        "rows": [
            ["BTC", "0.5", "50000", "52000", "+1000 #00ff00"],  # 绿色
            ["ETH", "10", "3000", "2800", "-2000 #ff0000"]      # 红色
        ]
    }
    LogStatus('`' + json.dumps(table) + '`')

4. 无参数按钮

python
def main():
    while True:
        # 定义按钮
        btn_start = {
            "type": "button",
            "cmd": "start",
            "name": "▶ 启动",
            "class": "btn btn-xs btn-success"
        }
        
        btn_stop = {
            "type": "button",
            "cmd": "stop",
            "name": "⏹ 停止",
            "class": "btn btn-xs btn-danger"
        }
        
        # 显示按钮
        LogStatus(f"{_D()} 策略控制: `{json.dumps(btn_start)}` `{json.dumps(btn_stop)}`")
        
        # 处理点击
        cmd = GetCommand()
        if cmd == "start":
            Log("策略已启动")
        elif cmd == "stop":
            Log("策略已停止")
        
        Sleep(3000)

5. 单输入框按钮 (input)

python
def main():
    while True:
        # 带输入框的按钮
        btn_buy = {
            "type": "button",
            "cmd": "buy",
            "name": "📈 买入",
            "class": "btn btn-xs btn-success",
            "input": {
                "name": "请输入买入金额 (USDT)",
                "type": "number",        # number / string / selected / boolean
                "defValue": 100
            }
        }
        
        LogStatus(f"`{json.dumps(btn_buy)}`")
        
        # 处理输入 - 返回格式: "buy:100"
        cmd = GetCommand()
        if cmd and cmd.startswith("buy:"):
            amount = float(cmd.split(":")[1])
            Log(f"执行买入: {amount} USDT")
        
        Sleep(3000)

6. 多输入框按钮 (group)

python
def main():
    while True:
        # 多参数下单按钮
        btn_order = {
            "type": "button",
            "cmd": "placeOrder",
            "name": "📝 下单",
            "class": "btn btn-xs btn-primary",
            "group": [
                {"name": "symbol", "description": "交易对", "type": "string", "defValue": "BTC"},
                {"name": "direction", "description": "方向", "type": "selected", "defValue": "做多|做空"},
                {"name": "orderType", "description": "类型", "type": "selected", "defValue": "市价|限价"},
                {"name": "price", "description": "价格", "type": "number", "defValue": 0},
                {"name": "amount", "description": "数量", "type": "number", "defValue": 100},
                {"name": "autoClose", "description": "自动平仓", "type": "boolean", "defValue": True}
            ]
        }
        
        LogStatus(f"`{json.dumps(btn_order)}`")
        
        # 处理输入 - 返回格式: 'placeOrder:{"symbol":"BTC","direction":0,"orderType":1,"price":42000,"amount":100,"autoClose":true}'
        cmd = GetCommand()
        if cmd and cmd.startswith("placeOrder:"):
            params = json.loads(cmd.split(":", 1)[1])
            direction = "做多" if params["direction"] == 0 else "做空"
            order_type = "市价" if params["orderType"] == 0 else "限价"
            Log(f"下单: {params['symbol']} {direction} {order_type}")
            Log(f"价格: {params['price']}, 数量: {params['amount']}")
        
        Sleep(3000)

7. 下拉多选按钮

python
def main():
    while True:
        btn_select = {
            "type": "button",
            "cmd": "selectCoins",
            "name": "🪙 选择币种",
            "class": "btn btn-xs btn-info",
            "input": {
                "name": "选择交易币种 (支持多选)",
                "type": "selected",
                "options": [
                    {"text": "比特币", "value": "BTC"},
                    {"text": "以太坊", "value": "ETH"},
                    {"text": "索拉纳", "value": "SOL"},
                    {"text": "币安币", "value": "BNB"}
                ],
                "defValue": ["BTC", "ETH"],  # 默认选中
                "multiple": True              # 允许多选
            }
        }
        
        LogStatus(f"`{json.dumps(btn_select)}`")
        
        # 返回格式: 'selectCoins:["BTC","ETH","SOL"]'
        cmd = GetCommand()
        if cmd and cmd.startswith("selectCoins:"):
            coins = json.loads(cmd.split(":", 1)[1])
            Log(f"已选择: {coins}")
        
        Sleep(3000)

8. 表格内按钮 - 单元格放按钮

8. 表格内按钮 - 单元格放按钮

python
def main():
    while True:
        # 持仓管理表格,每行带操作按钮
        table = {
            "type": "table",
            "title": "📊 持仓管理",
            "cols": ["币种", "方向", "数量", "均价", "盈亏", "操作"],
            "rows": [
                [
                    "BTC", "", "0.5", "42000", "+500 #00ff00",
                    {"type": "button", "cmd": "close_BTC", "name": "平仓", "class": "btn btn-xs btn-danger"}
                ],
                [
                    "ETH", "", "10", "2500", "-120 #ff0000",
                    {"type": "button", "cmd": "close_ETH", "name": "平仓", "class": "btn btn-xs btn-danger"}
                ]
            ]
        }
        
        LogStatus('`' + json.dumps(table) + '`')
        
        # 处理平仓
        cmd = GetCommand()
        if cmd == "close_BTC":
            Log("平仓 BTC")
        elif cmd == "close_ETH":
            Log("平仓 ETH")
        
        Sleep(3000)

9. 表格内按钮 - 单元格多个按钮

python
def main():
    while True:
        # 定义按钮(带输入框)
        btn_close = {
            "type": "button",
            "cmd": "close_BTC",
            "name": "平仓",
            "class": "btn btn-xs btn-danger",
            "input": {"name": "数量", "type": "number", "defValue": 0.5}
        }
        
        btn_add = {
            "type": "button",
            "cmd": "add_BTC",
            "name": "加仓",
            "class": "btn btn-xs btn-success",
            "group": [
                {"name": "price", "description": "价格", "type": "number", "defValue": 42000},
                {"name": "amount", "description": "数量", "type": "number", "defValue": 0.1}
            ]
        }
        
        # 一个单元格放多个按钮 - 使用数组
        table = {
            "type": "table",
            "title": "持仓操作",
            "cols": ["币种", "数量", "操作"],
            "rows": [
                ["BTC", "0.5", [btn_close, btn_add]]  # 数组 = 多按钮
            ]
        }
        
        LogStatus('`' + json.dumps(table) + '`')
        
        # 处理命令
        cmd = GetCommand()
        if cmd and cmd.startswith("close_BTC:"):
            amount = float(cmd.split(":")[1])
            Log(f"平仓 BTC: {amount}")
        elif cmd and cmd.startswith("add_BTC:"):
            params = json.loads(cmd.split(":", 1)[1])
            Log(f"加仓 BTC: 价格 {params['price']}, 数量 {params['amount']}")
        
        Sleep(3000)

10. 表格合并单元格

python
def main():
    table = {
        "type": "table",
        "title": "持仓汇总",
        "cols": ["币种", "数量", "成本", "盈亏"],
        "rows": [
            ["BTC", "0.5", "50000", "+1000"],
            ["ETH", "10", "30000", "-500"],
            # 横向合并 - colspan
            [{"body": "总计", "colspan": 3}, "+500"]
        ]
    }
    
    LogStatus('`' + json.dumps(table) + '`')

11. 组合布局 - 文字 + 按钮 + 表格

python
def main():
    while True:
        account = exchange.GetAccount()
        
        # 控制按钮
        btn_start = {"type": "button", "cmd": "start", "name": "▶ 启动", "class": "btn btn-xs btn-success"}
        btn_stop = {"type": "button", "cmd": "stop", "name": "⏹ 停止", "class": "btn btn-xs btn-danger"}
        btn_settings = {
            "type": "button",
            "cmd": "settings",
            "name": "⚙️ 设置",
            "class": "btn btn-xs btn-default",
            "group": [
                {"name": "leverage", "description": "杠杆", "type": "number", "defValue": 10},
                {"name": "takeProfit", "description": "止盈%", "type": "number", "defValue": 2.5}
            ]
        }
        
        # 持仓表格
        table = {
            "type": "table",
            "title": "当前持仓",
            "cols": ["币种", "数量", "盈亏"],
            "rows": [
                ["BTC", "0.5", "+500 #00ff00"],
                ["ETH", "10", "-120 #ff0000"]
            ]
        }
        
        # 组合显示
        status = ""
        status += f"{_D()} | 策略运行中 | 余额: {account['Balance']:.2f} USDT\n"
        status += f"控制: `{json.dumps(btn_start)}` `{json.dumps(btn_stop)}` `{json.dumps(btn_settings)}`\n"
        status += f"`{json.dumps(table)}`\n"
        status += "💡 点击按钮进行操作"
        
        LogStatus(status)
        
        # 处理命令
        cmd = GetCommand()
        if cmd:
            Log(f"收到命令: {cmd}")
        
        Sleep(3000)

12. 禁用按钮

python
def main():
    btn_disabled = {
        "type": "button",
        "cmd": "action",
        "name": "🚫 已禁用",
        "class": "btn btn-xs btn-default",
        "disabled": True,
        "description": "此按钮当前不可用"
    }
    
    LogStatus('`' + json.dumps(btn_disabled) + '`')

13. 完整示例 - 策略控制面板

python
import json

is_running = True
settings = {"leverage": 10, "takeProfit": 2.5, "stopLoss": 5.0}

def main():
    global is_running, settings
    
    while True:
        account = exchange.GetAccount()
        
        # 控制按钮
        btn_toggle = {
            "type": "button",
            "cmd": "stop" if is_running else "start",
            "name": "⏹ 暂停" if is_running else "▶ 启动",
            "class": "btn btn-xs btn-danger" if is_running else "btn btn-xs btn-success"
        }
        
        btn_refresh = {
            "type": "button",
            "cmd": "refresh",
            "name": "🔄 刷新",
            "class": "btn btn-xs btn-info"
        }
        
        btn_settings = {
            "type": "button",
            "cmd": "updateSettings",
            "name": "⚙️ 策略设置",
            "class": "btn btn-xs btn-default",
            "group": [
                {"name": "leverage", "description": "杠杆倍数", "type": "number", "defValue": settings["leverage"]},
                {"name": "takeProfit", "description": "止盈 (%)", "type": "number", "defValue": settings["takeProfit"]},
                {"name": "stopLoss", "description": "止损 (%)", "type": "number", "defValue": settings["stopLoss"]}
            ]
        }
        
        # 交易按钮
        btn_buy = {
            "type": "button",
            "cmd": "buy",
            "name": "📈 买入",
            "class": "btn btn-xs btn-success",
            "input": {"name": "金额 (USDT)", "type": "number", "defValue": 100}
        }
        
        btn_sell = {
            "type": "button",
            "cmd": "sell",
            "name": "📉 卖出",
            "class": "btn btn-xs btn-warning",
            "input": {"name": "金额 (USDT)", "type": "number", "defValue": 100}
        }
        
        btn_order = {
            "type": "button",
            "cmd": "placeOrder",
            "name": "📝 下单",
            "class": "btn btn-xs btn-primary",
            "group": [
                {"name": "symbol", "description": "币种", "type": "string", "defValue": "BTC"},
                {"name": "direction", "description": "方向", "type": "selected", "defValue": "做多|做空"},
                {"name": "price", "description": "价格", "type": "number", "defValue": 0},
                {"name": "amount", "description": "数量", "type": "number", "defValue": 100}
            ]
        }
        
        # 持仓表格
        position_table = {
            "type": "table",
            "title": "📊 当前持仓",
            "cols": ["币种", "方向", "数量", "均价", "盈亏", "操作"],
            "rows": [
                ["BTC", "", "0.5", "42000", "+500 #00ff00",
                 [
                     {"type": "button", "cmd": "close_BTC", "name": "平仓", "class": "btn btn-xs btn-danger",
                      "input": {"name": "数量", "type": "number", "defValue": 0.5}},
                     {"type": "button", "cmd": "add_BTC", "name": "加仓", "class": "btn btn-xs btn-success",
                      "input": {"name": "金额", "type": "number", "defValue": 100}}
                 ]
                ],
                ["ETH", "", "10", "2500", "-120 #ff0000",
                 [
                     {"type": "button", "cmd": "close_ETH", "name": "平仓", "class": "btn btn-xs btn-danger",
                      "input": {"name": "数量", "type": "number", "defValue": 10}},
                     {"type": "button", "cmd": "add_ETH", "name": "加仓", "class": "btn btn-xs btn-success",
                      "input": {"name": "金额", "type": "number", "defValue": 100}}
                 ]
                ]
            ]
        }
        
        # 组装状态栏
        status = f"{'🟢' if is_running else '🔴'} {_D()} | "
        status += f"余额: {account['Balance']:.2f} USDT | "
        status += f"杠杆: {settings['leverage']}x\n"
        status += f"控制: `{json.dumps(btn_toggle)}` `{json.dumps(btn_refresh)}` `{json.dumps(btn_settings)}`\n"
        status += f"交易: `{json.dumps(btn_buy)}` `{json.dumps(btn_sell)}` `{json.dumps(btn_order)}`\n"
        status += f"`{json.dumps(position_table)}`"
        
        LogStatus(status)
        
        # 处理命令
        cmd = GetCommand()
        if cmd:
            Log(f"📩 收到命令: {cmd}")
            
            if cmd == "start":
                is_running = True
                Log("✅ 策略已启动")
            elif cmd == "stop":
                is_running = False
                Log("⏸️ 策略已暂停")
            elif cmd == "refresh":
                Log("🔄 手动刷新")
            elif cmd.startswith("updateSettings:"):
                params = json.loads(cmd.split(":", 1)[1])
                settings["leverage"] = int(params["leverage"])
                settings["takeProfit"] = float(params["takeProfit"])
                settings["stopLoss"] = float(params["stopLoss"])
                Log(f"⚙️ 设置已更新: {settings}")
            elif cmd.startswith("buy:"):
                amount = float(cmd.split(":")[1])
                Log(f"📈 市价买入: {amount} USDT")
            elif cmd.startswith("sell:"):
                amount = float(cmd.split(":")[1])
                Log(f"📉 市价卖出: {amount} USDT")
            elif cmd.startswith("placeOrder:"):
                params = json.loads(cmd.split(":", 1)[1])
                direction = "做多" if params["direction"] == 0 else "做空"
                Log(f"📝 下单: {params['symbol']} {direction} 价格:{params['price']} 数量:{params['amount']}")
            elif cmd.startswith("close_"):
                symbol = cmd.split("_")[1].split(":")[0]
                amount = float(cmd.split(":")[1]) if ":" in cmd else 0
                Log(f"📉 平仓 {symbol}: {amount}")
            elif cmd.startswith("add_"):
                symbol = cmd.split("_")[1].split(":")[0]
                amount = float(cmd.split(":")[1]) if ":" in cmd else 0
                Log(f"📈 加仓 {symbol}: {amount} USDT")
        
        Sleep(3000)

JSON 格式规范

表格结构

python
{
    "type": "table",
    "title": "表格标题",
    "cols": ["列1", "列2", "列3"],
    "rows": [
        ["单元格1", "单元格2", "单元格3"],
        ["数据1", "数据2", "数据3"]
    ]
}

按钮结构

python
# 无参数按钮
{
    "type": "button",
    "cmd": "命令名",
    "name": "按钮文字",
    "class": "btn btn-xs btn-success"
}

# 单输入框按钮
{
    "type": "button",
    "cmd": "命令名",
    "name": "按钮文字",
    "class": "btn btn-xs btn-primary",
    "input": {
        "name": "提示文字",
        "type": "number",      # number / string / selected / boolean
        "defValue": 100
    }
}

# 多输入框按钮
{
    "type": "button",
    "cmd": "命令名",
    "name": "按钮文字",
    "class": "btn btn-xs btn-default",
    "group": [
        {"name": "参数1", "description": "说明1", "type": "number", "defValue": 100},
        {"name": "参数2", "description": "说明2", "type": "string", "defValue": "BTC"},
        {"name": "参数3", "description": "说明3", "type": "selected", "defValue": "选项1|选项2"},
        {"name": "参数4", "description": "说明4", "type": "boolean", "defValue": True}
    ]
}

# 下拉多选按钮
{
    "type": "button",
    "cmd": "命令名",
    "name": "按钮文字",
    "input": {
        "name": "提示文字",
        "type": "selected",
        "options": [
            {"text": "显示文字1", "value": "值1"},
            {"text": "显示文字2", "value": "值2"}
        ],
        "defValue": ["值1", "值2"],  # 默认选中
        "multiple": True             # 允许多选
    }
}

特殊单元格

python
# 合并列
{"body": "内容", "colspan": 2}

# 合并行
{"body": "内容", "rowspan": 3}

# 颜色文字
"文字内容 #ff0000"  # 红色
"文字内容 #00ff00"  # 绿色

# 单元格放按钮
{"type": "button", "cmd": "action", "name": "按钮"}

# 单元格放多个按钮
[
    {"type": "button", "cmd": "action1", "name": "按钮1"},
    {"type": "button", "cmd": "action2", "name": "按钮2"}
]

命令解析

GetCommand() 返回值格式

按钮类型返回格式示例
无参数"cmd""start"
单输入 (input)"cmd:value""buy:100"
多输入 (group)"cmd:{json}"'order:{"price":100,"amount":1}'
下拉单选"cmd:index""select:0" (选中第一项)
下拉多选"cmd:[values]"'select:["BTC","ETH"]'

通用解析模板

python
def handleCommand(cmd):
    if not cmd:
        return
    
    # 1. 无参数命令
    if cmd == "start":
        Log("启动策略")
        return
    
    # 2. 单参数命令 (cmd:value)
    if ":" in cmd and not cmd.split(":", 1)[1].startswith("{"):
        action, value = cmd.split(":", 1)
        
        if action == "buy":
            amount = float(value)
            Log(f"买入: {amount}")
        elif action == "close_BTC":
            amount = float(value)
            Log(f"平仓 BTC: {amount}")
        return
    
    # 3. 多参数命令 (cmd:{json})
    if ":" in cmd and cmd.split(":", 1)[1].startswith("{"):
        action, json_str = cmd.split(":", 1)
        params = json.loads(json_str)
        
        if action == "placeOrder":
            Log(f"下单: {params['symbol']} 价格:{params['price']} 数量:{params['amount']}")
        elif action == "updateSettings":
            Log(f"更新设置: {params}")
        return

注意事项

1. JSON 包裹

表格和按钮必须用反引号包裹:

python
# ✅ 正确
LogStatus('`' + json.dumps(table) + '`')

# ❌ 错误 - 缺少反引号
LogStatus(json.dumps(table))

2. 多组件组合

使用 \n 换行分隔:

python
status = f"{_D()}\n"                          # 文字
status += f"`{json.dumps(btn1)}`\n"           # 按钮
status += f"`{json.dumps(table)}`\n"          # 表格
status += f"`{json.dumps(btn2)}`"             # 按钮
LogStatus(status)

3. 更新频率

  • 建议间隔: >= 3 秒
  • 原因: 避免数据库写入压力
  • 实时更新: 只在状态变化时调用

4. 数据大小限制

  • 表格行数: 建议 < 100 行
  • JSON 大小: 建议 < 100KB
  • 超大表格: 使用分页或滚动模式

5. 转义问题

使用 json.dumps() 自动处理转义:

python
# ✅ 推荐
table = {"type": "table", "title": "持仓"}
LogStatus('`' + json.dumps(table) + '`')

# ❌ 不推荐 - 手动拼接易出错
LogStatus('`{"type":"table","title":"持仓"}`')

6. 命令冲突

避免 cmd 重复:

python
# ❌ 错误 - cmd 重复
btn1 = {"type": "button", "cmd": "close", "name": "平BTC"}
btn2 = {"type": "button", "cmd": "close", "name": "平ETH"}

# ✅ 正确 - cmd 唯一
btn1 = {"type": "button", "cmd": "close_BTC", "name": "平BTC"}
btn2 = {"type": "button", "cmd": "close_ETH", "name": "平ETH"}

相关函数