问题描述
我正在尝试实施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
这篇关于IB-Insync仅下一次StK订单(不会执行额外的买入或卖出)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!