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

Flask应用Webhook重复执行问题:TradingView重复止损致额外持仓

解决TradingView重复Webhook导致Flask重复执行订单的问题

现有代码的核心问题

你的代码已经尝试用锁和缓存拦截重复请求,但没处理好两个关键环节:

  1. 检查到缓存无重复后,没把当前请求的标识存入缓存,导致第二个并发请求进来时依然能通过检查,触发重复平仓。
  2. time.sleep(0.7)放在锁内会阻塞其他请求,完全没必要,反而拖慢响应速度。

修正后的代码方案

from flask import Flask, request
import json
from threading import Lock
from datetime import datetime, timedelta

app = Flask(__name__)
lock = Lock()
# 用字典实现带过期时间的缓存,存储格式:{请求唯一标识: 过期时间}
request_cache = {}

def clean_expired_cache():
    """清理过期的缓存条目,避免内存占用过高"""
    current_time = datetime.now()
    # 筛选出已过期的缓存键
    expired_keys = [key for key, expire_at in request_cache.items() if current_time > expire_at]
    for key in expired_keys:
        del request_cache[key]

@app.route('/webhook_pivot', methods=['POST'])
def webhook():
    # 解析请求数据
    data = json.loads(request.data)
    # 生成请求的唯一标识(按key排序后序列化,确保相同内容生成相同字符串)
    req_identifier = json.dumps(data, sort_keys=True)
    side = data['side']
    qty = int(data['qty']) * int(lot)  # 假设lot是你已定义的全局变量
    sym = data.get('symbol')  # 假设请求中包含symbol字段,用于持仓检查

    if side == "BUY":
        # 买入订单执行代码
        pass
    elif side == "FULL_EXIT_BUY" and check_symbol_and_position(sym):
        with lock:
            # 先清理过期缓存,避免无效条目干扰判断
            clean_expired_cache()
            # 检查是否是重复请求
            if req_identifier in request_cache:
                print("重复消息,忽略")
                return "Duplicate data, ignoring", 200
            
            # 标记当前请求为已处理,设置10秒过期(覆盖TradingView重复发送的时间窗口)
            request_cache[req_identifier] = datetime.now() + timedelta(seconds=10)
        
        # 平仓逻辑放在锁外,避免阻塞其他请求的处理
        # 这里写入你的BUY EXIT order执行代码
        print("执行平仓操作")
    
    return "Success", 200

# 你的持仓检查辅助函数(示例)
def check_symbol_and_position(symbol):
    # 实现你原本的持仓检查逻辑,返回布尔值
    return True

关键优化点说明

  1. 原子化缓存操作:在锁内完成「检查缓存-写入缓存」的操作,确保并发请求不会同时通过重复校验。
  2. 缓存过期机制:给缓存条目设置10秒过期时间,既可以拦截短时间内的重复Webhook,又不会让缓存无限占用内存。
  3. 锁范围优化:只在缓存操作时加锁,平仓逻辑放在锁外,避免不必要的请求阻塞,提升服务的并发处理能力。

额外可选优化

  • 如果TradingView允许自定义Webhook内容,建议给每个告警加唯一request_id字段,用这个ID作为缓存键,比序列化整个请求数据更高效。
  • 如果你部署Flask时用了多进程(比如gunicorn多worker),内存缓存会不共享,这时可以换成Redis等外部缓存来存储请求标识。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 20:10:35