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

Pythonanywhere运行币安异步交易脚本卡在await语句问题求助

问题描述

我尝试在Pythonanywhere.com平台运行如下Python脚本,程序运行时卡在main函数while循环内的await语句处,但该代码在本地电脑上可无错误正常运行。

代码片段

async def main(coin, minQty, minNotional, histdata, open_position=False, cross_below=True, gotbalance=False):
    bm = BinanceSocketManager(client)
    ts = bm.trade_socket(coin)
    last_high = 0
    async with ts as tscm:
        while True:
            res = await tscm.recv()
            if res:
                frame = createframe(res)
                if last_high < frame.Price[0]:
                    last_high = frame.Price[0]

完整代码

import nest_asyncio
import asyncio
import pandas as pd
from binance import BinanceSocketManager
from binance.client import Client
from keys import api_key, api_secret
import numpy as np
from datetime import datetime
import winsound
import urllib.request

nest_asyncio.apply()

client = Client(api_key, api_secret)

ST = 7
LT = 25
coin = 'BTCUSDT'


def gethistoricals(symbol, LT):
    df = pd.DataFrame(client.get_historical_klines(symbol, '5m', str((LT - 1) * 5) + 'mins ago UTC'))
    df = df.iloc[:, :6]
    df.columns = ['Timestamp', 'Open', 'High', 'Low', 'Close', 'Volume']

    df.Open = df.Open.astype('float')
    df.High = df.High.astype('float')
    df.Low = df.Low.astype('float')
    df.Close = df.Close.astype('float')
    df.Volume = df.Volume.astype('float')

    df['ST'] = df.Close.rolling(ST - 1).mean()
    df['LT'] = df.Close.rolling(LT - 1).mean()
    high_low = df['High'] - df['Low']
    high_close = np.abs(df['High'] - df['Close'].shift())
    low_close = np.abs(df['Low'] - df['Close'].shift())

    ranges = pd.concat([high_low, high_close, low_close], axis=1)
    true_range = np.max(ranges, axis=1)

    df['ATR'] = true_range.rolling(14).sum()/14
    df['Datetime'] = df['Timestamp'].iloc[-1]
    df.Datetime = pd.to_datetime(df.Datetime, unit='ms')
    df.dropna(inplace=True)
    # print(df)
    return df


def liveSMA(hist, live):
    liveST = (hist['ST'].values + live.Price.values) / ST
    liveLT = (hist['LT'].values + live.Price.values) / LT
    return liveST, liveLT


def createframe(msg):
    df = pd.DataFrame([msg])
    df = df.loc[:, ['E', 's', 'E', 'p']]
    df.columns = ['Timestamp', 'symbol', 'Time', 'Price']
    df.Price = df.Price.astype(float)
    df.Time = pd.to_datetime(df.Time, unit='ms')
    return df


pnl = []


async def main(coin, minQty, minNotional, histdata, open_position=False, cross_below=True, gotbalance=False):
    bm = BinanceSocketManager(client)
    ts = bm.trade_socket(coin)
    last_high = 0
    async with ts as tscm:
        while True:
            res = await tscm.recv()
            if res:
                frame = createframe(res)
                if last_high < frame.Price[0]:
                    last_high = frame.Price[0]
                last_hist_time = datetime.strptime(
                    str(np.datetime_as_string(histdata['Datetime'].values[0], unit='ms')), '%Y-%m-%dT%H:%M:%S.%f')

                if int((frame.Time[0] - last_hist_time).total_seconds()) >= 305:
                    histdata = gethistoricals(coin, LT)
                livest, livelt, atr = histdata['ST'].values, histdata['LT'].values, histdata['ATR'].values
                try:
                    if not open_position:
                        if not gotbalance:
                            balance = client.get_asset_balance(asset='USDT')
                            balance = float(balance['free'])*0.95
                            gotbalance = True
                            if balance >= minNotional:
                                qty = round(balance/frame.Price[0], 5)
                                print(qty)
                                print(livest[0] > livelt[0], cross_below, qty >= minQty)
                            else:
                                print('Minimum Notional Error')
                        if livest[0] > livelt[0] and cross_below and qty >= minQty:
                            order = client.create_order(symbol=coin,
                                                        side='BUY',
                                                        type='MARKET',
                                                        quantity=qty)
                            print(order)
                            buyprice = float(order['fills'][0]['price'])
                            winsound.Beep(1000, 100)
                            open_position = True
                            cross_below = False
                    if open_position:
                        if frame.Price[0] < (last_high - (2 * atr[0])) or livest[0] < livelt[0]:
                            print(f'SL Trigger: {frame.Price[0] < (last_high - (2 * atr[0]))}')
                            print(f'Cross Trigger: {livest[0] < livelt[0]}')
                            order = client.create_order(symbol=coin,
                                                        side='SELL',
                                                        type='MARKET',
                                                        quantity=qty)
                            print(order)
                            sellprice = float(order['fills'][0]['price'])
                            winsound.Beep(1000, 100)
                            open_position = False
                            print(f'PnL : {(buyprice - sellprice) / buyprice}')
                            pnl.append((buyprice - sellprice) / buyprice)
                            print(f'Mean PnL : {np.mean(pnl)}')
                    if livest[0] < livelt[0]:
                        cross_below = True
                except Exception as e:
                    print(e)


if __name__ == "__main__":
    winsound.Beep(1000, 100)
    info = client.get_symbol_info(coin)
    # print(info)
    minQty = float(info['filters'][2]['minQty'])
    minNotional = float(info['filters'][3]['minNotional'])

    historicals = gethistoricals(coin, LT)
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(coin, minQty, minNotional, historicals))
原因与解决方案

核心原因

  • winsound是Windows平台专属库,Pythonanywhere服务器为Linux系统,导入该库会直接触发运行错误,本地Windows环境无此问题。
  • Pythonanywhere免费账户的出站网络做了限制,仅允许白名单站点的HTTP/HTTPS请求走官方代理,币安WebSocket接口使用wss协议,不受免费层支持,会导致连接无法建立,await tscm.recv()进入无限等待状态。
  • Binance客户端未设置超时参数,网络不通时会无限等待返回。

修复步骤

  1. 移除所有winsound相关代码,包括import winsound和所有winsound.Beep()调用,适配Linux运行环境。
  2. 初始化客户端时增加超时参数,避免无限制等待:
client = Client(api_key, api_secret, requests_params={'timeout': 30})
  1. 给WebSocket接收逻辑增加超时处理,卡住时自动触发重连:
# 替换原来的res = await tscm.recv()
try:
    res = await asyncio.wait_for(tscm.recv(), timeout=30)
except asyncio.TimeoutError:
    print("WebSocket连接超时,准备重连")
    break
  1. 如果使用Pythonanywhere免费账户,升级到付费套餐解锁全端口出站权限,免费层不支持自定义WebSocket连接。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 22:06:03