我在Heroku上运行了一个Python-Binance flask 应用程序,我用它来接收来自TradingView的交易警报,并通过API在Binance上执行交易。
我有一个WebSocket设置来监控当前的市场价格,我使用一个函数来监控现货市场的“未平仓交易”,一旦达到止盈就关闭它们。
该应用程序工作正常,但我收到通知Heroku说:
2023年3月13日00:51:10.044146+00:00黑鹿[网页1]:错误R14(超出内存配额)2023-03- 13 T00:51:32.620715+00:00 heroku[web.1]:工艺运行mem= 632 M(123.5%)
我已经将问题隔离到check_tp()函数(当禁用时,我没有内存泄漏)。
有没有人知道是什么导致了泄漏以及如何解决它?我在下面附上了check_tp函数的代码:
def process_stream_data(binance_websocket_api_manager):
while True:
try:
if binance_websocket_api_manager.is_manager_stopping():
exit(0)
oldest_data = binance_websocket_api_manager.pop_stream_data_from_stream_buffer()
is_empty = is_empty_message(oldest_data)
if is_empty:
time.sleep(0.01)
else:
oldest_data_dict = json.loads(oldest_data)
data = oldest_data_dict['data']
# Handle price change
handle_price_change(symbol=data['s'], timestamp=data['T'], price=data['p'])
except Exception as e:
print(f"Error processing websocket stream data: {e}")
# Attempt to reconnect to the websocket server
print("Attempting to reconnect to websocket server...")
binance_websocket_api_manager.stop_stream(oldest_data)
binance_websocket_api_manager.start()
time.sleep(5) # Wait for 5 seconds before attempting to process stream data again
cache = redis.from_url(os.environ.get("REDIS_URL"))
def handle_price_change(symbol, timestamp, price):
for s in the_pairs:
if symbol==s:
global_prices_write(symbol,price)
last_execution_time = cache.get('last_execution_time')
last_stream_check = cache.get('last_stream_check')
current_time = time.time()
if not last_execution_time or current_time - float(last_execution_time) >= 15:
cache.set('last_execution_time', current_time)
check_tp()
if not last_stream_check or current_time - float(last_stream_check) >= 300:
cache.set('last_stream_check', current_time)
print(global_prices["BTCBUSD"],"STREAM CHECK OK")
def check_tp():
#print(f"Initial memory usage: {process.memory_info().rss / 1024 / 1024:.2f} MB")
#print("Checking TPs")
opt = get_google_open_trades()
#print(f"Memory usage after get_google_open_trades(): {process.memory_info().rss / 1024 / 1024:.2f} MB")
sets = get_google_settings()
#print(f"Memory usage after get_google_settings(): {process.memory_info().rss / 1024 / 1024:.2f} MB")
for td in opt:
if td[0]=="Account":
continue
perc = 0.0
sym = td[4]
order_id = td[2]
acc = td[0].lower()
price = td[5]
for s in sets:
if s[0].lower() == acc:
take_profit = s[3]
break
price_float = 0.0
price_float=float(price)
TP = 0.0
TP = float(take_profit)
target = float(price_float) + ((float(price_float) * TP) / 100)
if float(TP) > 0 and float(global_prices_read(sym)) >= target:
bnan = Client(API_KEYS[acc], API_SECRETS[acc], tld='com')
inf = bnan.get_my_trades(symbol=sym, orderId=order_id)
trades = []
for ele in inf:
trades.append(ele)
sell_commission = 0.0
for td in trades:
if td["orderId"] == order_id:
sell_commission += float(td["commission"])
newquant = float(td['executedQty']) - float(sell_commission)
rnd_quantity = format_quantity(sym, newquant, global_prices[sym],bnan)
order_response = order(binance, "SELL", rnd_quantity, sym, td['clientOrderId'])
if order_response['side'].upper() == "SELL":
remove_google_open_trade(order_response['clientOrderId'])
print(order_response)
del opt
del sets
gc.collect()
enter image description here
该函数还引用了我对Google Sheets API的调用:
def get_google_open_trades():
# Get all data from the sheet
result = service.spreadsheets().values().get(
spreadsheetId=spreadsheet_id,
range=f'{open_trades_sheet_name}!A:F', # specify range A:F to include all columns up to F
valueRenderOption='UNFORMATTED_VALUE',
dateTimeRenderOption='FORMATTED_STRING'
).execute()
data = result.get('values', [])
# Find the last row containing data
last_row = len(data)
while last_row > 0:
row_data = data[last_row-1]
if any(row_data): # check if the row contains any non-empty cells
break
last_row -= 1
# Trim any empty rows after the last row containing data
data = data[:last_row]
# Print the data to the console
if not data:
print('No data found.')
else:
return data
def get_google_settings():
# Get the last row and column of data in the sheet
result = service.spreadsheets().values().get(
spreadsheetId=spreadsheet_id,
range=f'{sheet_name}!E:E',
valueRenderOption='UNFORMATTED_VALUE',
dateTimeRenderOption='FORMATTED_STRING'
).execute()
last_row = len(result.get('values', []))
result = service.spreadsheets().values().get(
spreadsheetId=spreadsheet_id,
range=f'{sheet_name}!1:1',
valueRenderOption='UNFORMATTED_VALUE',
dateTimeRenderOption='FORMATTED_STRING'
).execute()
last_col = len(result.get('values', [])[0])
# Update the range to fetch all data up to the last row and column
range_name = f"{sheet_name}!A1:F{last_row}"
# Get all data from the sheet
result = service.spreadsheets().values().get(
spreadsheetId=spreadsheet_id,
range=range_name,
valueRenderOption='UNFORMATTED_VALUE',
dateTimeRenderOption='FORMATTED_STRING'
).execute()
data = result.get('values', [])
# Print the data to the console
if not data:
print('No data found.')
else:
return data
我尝试过使用gc.collect()强制垃圾收集,并限制函数运行的次数。
1条答案
按热度按时间0yycz8jy1#
https://devcenter.heroku.com/articles/limits#dynos
Heroku记忆力有限
现有程序可能已经有了比较高的内存,当
check_tp
在执行过程中超过负荷的时候,check_tp里面临时变量比较多,内存比较高频,可以适当的优化程序,当然更有可能是因为opt = get_google_open_trades()
和sets = get_google_settings()
,建议检查一下,当执行到这里的时候,在这两个之前和之后的存储容量。这只是一些建议,希望能对你有所帮助