IB-Insync仅下一次StK订单(不会执行额外的买入或卖出)

问题描述

我正在尝试实施TradingView/Interactive Brokers API,使用IB-Insync通过TradingView网络挂钩警报自动向Interactive Brokers TW下单。我花了很多时间试图解决为什么TWS API只执行一个订单,而不是收到其他订单,并且无法解决问题或解决方案(因为我还有很多要学习)。我让WebHook警报正常工作,将数据发送到数据库,还触发了异步消息检查器、Redis数据库,并成功注册到Flask应用程序,没有出现错误消息。

当我使用InSomnia REST发送一个JSON WebHook Stock MKT Order(AAPL)来测试该API时,它会完美地发送到TWS,并记录在API日志中。但这种情况只会发生一次。如果我尝试通过InSominia发送另一个JSON WebHook订单,或由TradingView WebHook自动触发;该订单将在除TWS之外的所有内容中注册,并且TWS API日志中不记录任何内容。如果我随后尝试测试发送一个不同的股票报价器(例如,MSFT),JSON WebHook在Ayncio消息检查器、Redis数据库和Flask应用程序上注册时没有错误,但同样没有订单在TWS中处理,在API日志文件中也没有任何内容。 然后几个小时后,如果我试一试,它可能会起作用。在过去的一个小时里,我又尝试了5次,但都不起作用,而且自从上次使其起作用以来,我没有任何改变。

我被自己做错了什么难倒了。这可能是TWS API设置中的设置吗?根据IB API文件,是否需要唯一的交易ID或合同ID号?(我对IB-Insync的研究发现,这并不是必需的--我找到了Ewald de Wit的帖子,暗示这些帖子是自动生成的;但我可能错了)。如果需要,如何对其进行编码以生成缩放唯一ID。

以前有没有人经历过这种情况并且知道解决方案?

非常感谢

IB-Insync Python、WebHook和App python代码如下,如果有帮助,我已附加了一个日志文件:

import redis, json
from ib_insync import *
import asyncio, time, random

# connect to Interactive Brokers 
ib = IB()
ib.connect('127.0.0.1', 7497, clientId=1)

# connect to Redis and subscribe to tradingview messages
r = redis.Redis(host='localhost', port=6379, db=0)
p = r.pubsub()
p.subscribe('tradingview')

async def check_messages():
    print(f"{time.time()} - checking for tradingview webhook messages")
    message = p.get_message()
    if message is not None and message['type'] == 'message':
        print(message)

        message_data = json.loads(message['data'])

        stock = Stock(message_data['ticker'], 'SMART', 'USD')
        order = MarketOrder(message_data['strategy']['order_action'], message_data['strategy']['order_contracts'])
        trade = ib.placeOrder(stock, order)

async def run_periodically(interval, periodic_function):
    while True:
        await asyncio.gather(asyncio.sleep(interval), periodic_function())

asyncio.run(run_periodically(1, check_messages))

ib.run()

App Python代码:

import redis, sqlite3, time
from flask import Flask, render_template, request, g, current_app

app = Flask(__name__)

r = redis.Redis(host='localhost', port=6379, db=0)

conn = sqlite3.connect('trade.db')
cursor = conn.cursor()
cursor.execute("""
    CREATE TABLE IF NOT EXISTS signals (
        timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, 
        ticker,
        order_action,
        order_contracts,
        order_price
    )
""")
conn.commit()

def get_db():
    if 'db' not in g:
        g.db = sqlite3.connect('trade.db')
        g.db.row_factory = sqlite3.Row

    return g.db

@app.get('/')
def dashboard():
    db = get_db()
    cursor = db.cursor()
    cursor.execute("""
        SELECT * FROM signals
    """)
    signals = cursor.fetchall()

    return render_template('dashboard.html', signals=signals)

@app.post("/webhook")
def webhook():
    data = request.data

    if data:
        r.publish('tradingview', data)

        data_dict = request.json

        db = get_db()
        cursor = db.cursor()
        cursor.execute("""
            INSERT INTO signals (ticker, order_action, order_contracts, order_price) 
            VALUES (?, ?, ?, ?)
        """, (data_dict['ticker'], 
                data_dict['strategy']['order_action'], 
                data_dict['strategy']['order_contracts'],
                data_dict['strategy']['order_price']))

        db.commit()

        return data

    return {
        "code": "success"
    }

已填充数据的JSON WebHook代码:

{
    "passphrase": "########",
    "time": "2021-09-05T19:49:00Z",
    "ticker": "AAPL",
    "bar": {
        "time": "2021-09-05T19:48:00Z",
        "open": 126.35,
        "high": 128.02,
        "low": 126.02,
        "close": 127.75,
        "volume": 12345
    },
    "strategy": {
        "position_size": 1,
        "order_action": "BUY",
        "order_contracts": 1,
        "order_price": 128.50,
        "order_id": "Close entry(s) order long",
        "market_position": "long",
        "market_position_size": 1,
        "prev_market_position": "flat",
        "prev_market_position_size": 0
    }
}

解决方案

与此处讨论相关:https://groups.io/g/twsapi/topic/4045569

您需要唯一地初始化orderId

order = LimitOrder("BUY", 1, 0.05)
order.orderId = # unique positive integer number 
ib.qualifyContracts(contract)  
ib.placeOrder(contract, order) // this  placeOrder will change the order.orderId

相关文章