Python websockets的on_message函数无法传参时,除global外有什么替代方案
不用global关键字的实现方案
以下方案均可以保留跨消息的状态持久化,不需要每次接收消息时重置变量:
1. 类封装状态(最推荐)
把所有交易相关的参数、状态变量、回调逻辑都封装到同一个类中,on_message作为类的实例方法,通过self访问所有状态变量,完全不需要全局变量,可维护性最高,也方便后续扩展功能。
示例代码:
import json import websocket class TradingBot: def __init__(self): # 初始化所有参数和状态 self.Symbol = "BTCUSDT" self.interval = "1m" self.EMA_period = 28 self.MACD_fast_period = 12 self.MACD_slow_period = 26 self.MACD_signal_period = 9 self.historic_highs = [] self.historic_lows = [] self.historic_closes = [] self.MACD_CrossBool = [None, None] self.in_position = False # 其他需要的参数也可以放在这里 def on_message(self, ws, message): # ------------------------- 解析JSON消息数据 ------------------------- # json_message = json.loads(message) candle = json_message['k'] # 访问K线数据 # ......[其他代码省略]...... if MACD_CrossOver == True and trend == 1: if not self.in_position: print("买入订单") self.in_position = True if MACD_CrossUnder == True and trend == -1: if not self.in_position: print("卖出订单") self.in_position = True # ......[其他代码省略]...... if self.in_position: if buy_order['status'] and close <= long_stop_price: sell_order = margin_order(buy_order['symbol'], SIDE_SELL, buy_order['quantity'], close, ORDER_TYPE_LIMIT) print("多头止损触发") if sell_order['status'] and close >= short_stop_price: buy_order = margin_order(sell_order['symbol'], SIDE_BUY, sell_order['quantity'], close, ORDER_TYPE_LIMIT) print("空头止损触发") # 实例化后绑定回调 if __name__ == "__main__": bot = TradingBot() ws = websocket.WebSocketApp( url="你的websocket连接地址", on_message=bot.on_message # 其他回调比如on_error、on_close也可以绑定bot的对应方法 ) ws.run_forever()
2. 可变容器包装状态(改动最小)
Python中只有对变量重新赋值时才需要声明global,如果是修改可变对象(列表、字典)的内部元素,不需要声明全局。你可以把布尔类型的in_position包装到列表或者字典这类可变容器中,仅改一行定义就能解决问题。
示例代码:
# 原来的定义:in_position = False # 改成用长度为1的列表包装 in_position = [False] def on_message(ws, message): # 不需要加global声明 json_message = json.loads(message) candle = json_message['k'] # ......[其他代码省略]...... if MACD_CrossOver == True and trend == 1: # 读写都用下标访问第一个元素 if not in_position[0]: print("买入订单") in_position[0] = True # 其他用到in_position的地方全部改成in_position[0]即可
3. 闭包封装状态
用外层函数包裹所有状态变量,返回on_message回调函数,内部通过nonlocal关键字修改外层作用域的变量,不会污染全局命名空间。
示例代码:
def create_trading_callback(): Symbol = "BTCUSDT" interval = "1m" EMA_period = 28 MACD_fast_period = 12 MACD_slow_period = 26 MACD_signal_period = 9 historic_highs = [] historic_lows = [] historic_closes = [] MACD_CrossBool = [None, None] in_position = False def on_message(ws, message): # 声明需要修改外层作用域的变量 nonlocal in_position json_message = json.loads(message) candle = json_message['k'] # ......[其他代码省略]...... if MACD_CrossOver == True and trend == 1: if not in_position: print("买入订单") in_position = True # 其他逻辑和原来完全一致 return on_message # 绑定回调时传入生成的on_message函数 if __name__ == "__main__": on_message_cb = create_trading_callback() ws = websocket.WebSocketApp( url="你的websocket连接地址", on_message=on_message_cb ) ws.run_forever()
4. 用functools.partial绑定状态参数
你可以提前把状态变量包装到字典里,用functools.partial把状态字典绑定为on_message的额外参数,不需要改动回调的核心逻辑。
示例代码:
from functools import partial # 把所有状态放到字典中 state = { "Symbol": "BTCUSDT", "interval": "1m", "EMA_period": 28, "MACD_fast_period": 12, "MACD_slow_period": 26, "MACD_signal_period": 9, "historic_highs": [], "historic_lows": [], "historic_closes": [], "MACD_CrossBool": [None, None], "in_position": False } # 给on_message加一个state参数 def on_message(state, ws, message): json_message = json.loads(message) candle = json_message['k'] # ......[其他代码省略]...... if MACD_CrossOver == True and trend == 1: if not state["in_position"]: print("买入订单") state["in_position"] = True # 其他用到状态的地方都从state字典里取 # 绑定回调时用partial把state传进去 if __name__ == "__main__": bound_on_message = partial(on_message, state) ws = websocket.WebSocketApp( url="你的websocket连接地址", on_message=bound_on_message ) ws.run_forever()
内容的提问来源于stack exchange,提问作者Mo0rBy
相关产品推荐
相关产品推荐

