IB-Insync only place Stk order once (will not execute additional buy or sell) and I am unable to Futures contract orders to execute at all

  flask, interactive-brokers, python, redis, webhooks

I am trying to implement a Tradingview/Interactive Brokers API using IB-Insync to automatically place orders with Interactive Brokers TWS via tradingview webhook alerts. I have consumed a lot of time trying to resolve why TWS API is only executing one order, and not others received and cannot work out the problem nor solution (as i still have a lot to learn). I have the webhook alerts working, sending data to a database, and also triggering a asyncio message checker, Redis database and registering on the Flask application successfully with no error messages.

When i trial the API using Insomnia REST sending a JSON webhook Stock MKT order (AAPL) it sends through to TWS perfectly and records in the API Log. But this only happens once. If i try to send another JSON webhook order through Insominia, or automatically triggered by the Tradingview Webhook; the order is registered in everything except TWS and nothing is recorded in the TWS API log. If i then try to test send a different stock ticker (e.g. MSFT), the JSON webhook registers on the asyncio message checker, the Redis database and the flask application with no errors, but again no order is processed in TWS and nothing in the API Log file.
Then a few hours later if i try – it may work. I have tried another 5 times over the last hour and it has not worked, and i havent changed anything since i last got it to work.

I am stumped as to what i have done wrong. Could it be a setting in the TWS API settings? Is a unique trade ID or contract ID number required as per the IB API docs? (my research into IB-Insync finds this isnt required – i have found posts by Ewald de Wit implying these are automatically generated; but i could be wrong). How would this be coded to produce a scaling unique id if it is required.

Has anybody experienced this before and know of a resolution?

Many thanks

IB-Insync python, webhook, and App python code below, and i have attached a log file if this helps:

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 code:

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 Code with filled in data:

{
    "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
    }
}

Source: Python Questions

LEAVE A COMMENT