Log
LogStatus()
记录状态信息到状态栏,支持表格、按钮、输入框等富文本交互控件。
语法
python
LogStatus(*msgs)参数
| 参数名 | 类型 | 必选 | 默认值 | 说明 |
|---|---|---|---|---|
| *msgs | any | 否 | - | 一个或多个状态消息,支持: |
返回值
无
说明
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"}相关函数
- GetCommand() - 接收按钮交互数据
- Log() - 记录普通日志
- LogReset() - 清空日志