You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PySimpleGUI点击按钮无法触发绑定的Coinbase下单函数问题

问题描述

基于Coinbase Crypto Exchange沙箱API开发了加密货币市价单交易程序,无GUI场景下代码运行完全正常。为提升易用性,计划开发图形界面,实现点击按钮即可触发对应功能,无需逐行运行代码。

完成基础GUI开发、将市价买入逻辑封装为独立函数后,无法通过界面按钮触发交易执行。已尝试调整函数调用位置、修改代码排布顺序,甚至将全部相关代码移入买入函数中,问题仍未解决。初步猜测买入订单无法执行是买入逻辑代码与其余代码分离导致,验证后该假设不成立。


客户端初始化代码

import pandas as pd
import cbpro
import PySimpleGUI as sg    

api_secret =  # 需填入自身API密钥
api_key =     # 需填入自身API密钥
api_pass =    # 需填入自身API密码

# 创建API客户端
url='https://api-public.sandbox.pro.coinbase.com'

client = cbpro.AuthenticatedClient(
    api_key,
    api_secret,
    api_pass,
    api_url=url
)

行情WebSocket获取代码

#websocket
class TextWebsocketClient(cbpro.WebsocketClient):
    # 连接建立逻辑
    def on_open(self):
        self.url           = 'wss://ws-feed-public.sandbox.pro.coinbase.com'  # 连接端点
        self.message_count = 0
    
    # 消息接收逻辑
    def on_message(self,msg):   
        self.message_count += 1
        msg_type = msg.get('type',None)
        if msg_type == 'ticker':
            # 提取需要的字段
            time_val   = msg.get('time',('-'*27))
            price_val  = msg.get('price',None)
            if price_val is not None:
                price_val = float(price_val)
            product_id = msg.get('product_id',None)
            
            print(f"{time_val:40} {price_val:.3f} {product_id}\tchannel type: {msg_type}")
    
    def on_close(self):
        print(f"<---Websocket connection closed--->\n\tTotal messages: {self.message_count}")
        
# 启动行情流,连接断开或主动关闭时停止
stream = TextWebsocketClient(products=['BTC-USD'],channels=['ticker'])
stream.start()

#stream.close()
print ("Stream closed")

封装的市价买入函数

注:该段逻辑在非函数、非GUI场景下运行完全正常,封装为函数被GUI按钮调用时无法正常执行

# 市价买单下单
def buy():
    client.place_market_order(product_id='BTC-USD',side='buy',funds=100)
    accounts = client.get_accounts()
    
    for acc in accounts:
        currency = acc.get('currency')
        if currency=='BTC':
            acc_id = acc.get('id')

    acc_history = client.get_account_history(acc_id)
    return "Buy Complete"

GUI界面代码

# GUI 布局
sg.theme('DarkGreen')
layout = [ 
            [sg.Text("Welcome to your Crypto Launch Pad!\n Select a command...")],
            [sg.Button('Buy')],
            [sg.Button('Sell')],
            [sg.Button('Current Price')],
            [sg.Button('Profit/Loss')],
            [sg.Button('Exit')]
    
         ]
 
window = sg.Window('Crypto Buy/Sell Launch Pad', layout, size = (400, 400)) # 窗口标题

# 事件循环
while True:
    event, values = window.read()
    print(event, values)
    if event is None or event == "Exit":
        break
    
    if event == "Buy":   # 绑定买入函数
        buy()
        print(buy())
        
window.close()

排查方向与修复方案
  • 核心问题:WebSocket阻塞主线程
    cbpro库的WebsocketClient.start()方法默认以阻塞模式运行,会占用当前线程无限循环接收消息。按现有代码顺序,执行到stream.start()时就会卡住,后续GUI初始化、事件循环的代码根本不会执行。非GUI场景下是顺序执行逻辑,阻塞不影响后续下单操作,但GUI必须靠主线程持续运行事件循环才能响应按钮点击。修复方式是启动WebSocket时传入线程参数,让行情流在后台子线程运行:
    stream.start(threaded=True)
    
  • 缺少接口响应捕获,报错无感知
    现有buy()函数没有接收下单接口的返回值,即使接口返回鉴权失败、参数错误、余额不足等报错,也不会有任何提示。建议先接收接口返回值打印排查:
    def buy():
        order_resp = client.place_market_order(product_id='BTC-USD',side='buy',funds=100)
        print("下单接口返回:", order_resp) # 打印返回内容定位报错
        # 后续逻辑不变
    
  • 重复触发下单问题
    GUI事件逻辑中连续调用了两次buy():一次直接调用,一次在print(buy())时又调用一次,会触发重复下单,删除其中一次调用即可。
  • 变量作用域隐患
    buy()函数中的acc_id变量仅在for循环匹配到BTC账户时才会赋值,如果接口返回的账户列表中没有BTC币种,后续调用get_account_history(acc_id)会直接触发未定义变量报错,建议提前初始化acc_id并加异常判断。

内容的提问来源于stack exchange,提问作者dingoyum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 18:06:25