def openpositions_fromwikipedia(ib, db, accid, scancode): try: tickers = save_tickers( 'http://en.wikipedia.org/wiki/List_of_S%26P_500_companies') # tickers= save_tickers('https: // en.wikipedia.org / wiki / NASDAQ - 100 # Components') # tickers= save_tickers('https://www.nasdaq.com/quotes/nasdaq-100-stocks.aspx') for ticker in tickers: cnt = ibsync.Contract(symbol=ticker, secType=cf.myscaninstrument, currency=cf.mycurrency, exchange=cf.myprefexchange) isopen = ibdb.positionisopen(db, accid, ticker) if ib.qualifyContracts(cnt) != [] and not isopen: try: breakout = requesthistoricaldata(ib, cnt, cf.myprdnum, cf.myprdscale, cf.mybarsixe) except ValueError as e: print(e, cnt) continue if breakout > 0: ibdb.dbfill_fundamentals(db, accid, fillfundamentals(ib, db, [cnt])) opennewoption(ib, db, cnt, "SELL", "P", cf.myoptselldte, scancode) elif breakout < 0: ibdb.dbfill_fundamentals(db, accid, fillfundamentals(ib, db, [cnt])) opennewoption(ib, db, cnt, "SELL", "C", cf.myoptselldte, scancode) except Exception as err: #error_handling(err) raise
def get_state(self): """ Handle interactions with API and raise related exceptions here """ self.connect_to_gateway() self.ptf = self.ib.portfolio() self.options = [ p.contract for p in self.ptf if p.contract.secType == 'OPT' ] self.options = self.ib.qualifyContracts(*self.options) self.tickers = self.ib.reqTickers(*self.options) # get underlying contracts and tickers underConIds = [ self.ib.reqContractDetails(c)[0].underConId for c in self.options ] underContracts = [ib_insync.Contract(conId=c) for c in underConIds] underContracts = self.ib.qualifyContracts(*underContracts) underTickers = self.ib.reqTickers(*underContracts) df_under = ib_insync.util.df(underTickers) df_under['price'] = df_under.apply(self.price_getter, axis=1) df_under = df_under[['contract', 'price']].add_suffix('_und') df = pd.concat([ ib_insync.util.df(self.options), ib_insync.util.df(self.tickers), df_under ], axis=1) df['option_price'] = df.apply(self.price_getter, axis=1) self.options = df self.ib.disconnect()
def get_optionfromunderlying(cnt, optright, strike, expdate): try: # preparem el nou trade: definim i qualifiquem la nova opció option = ibsync.Contract() option.symbol = cnt.symbol option.strike = strike option.secType = "OPT" option.exchange = cf.myprefexchange option.currency = cnt.currency option.right = optright option.lastTradeDateOrContractMonth = expdate return option except Exception as err: # error_handling(err) raise
def contract_from_specifier( specifier: ContractSpecifier) -> ib_insync.Contract: """ Converts a ContractSpecifier into an ib_insync Contract object. This does not guarantee that the resulting Contract actually refers to a real security. """ security_type_mapping = { ContractSpecifier.SecurityType.STOCK: "STK", ContractSpecifier.SecurityType.OPTION: "OPT", ContractSpecifier.SecurityType.FUTURE: "FUT", ContractSpecifier.SecurityType.INDEX: "IND", ContractSpecifier.SecurityType.FUTURES_OPTION: "FOP", ContractSpecifier.SecurityType.CASH: "CASH", ContractSpecifier.SecurityType.CFD: "CFD", ContractSpecifier.SecurityType.COMBO: "BAG", ContractSpecifier.SecurityType.WARRANT: "WAR", ContractSpecifier.SecurityType.BOND: "BOND", ContractSpecifier.SecurityType.COMMODITY: "CMDTY", ContractSpecifier.SecurityType.NEWS: "NEWS", ContractSpecifier.SecurityType.FUND: "FUND", } right_mapping = { ContractSpecifier.Right.UNSPECIFIED_RIGHT: "", ContractSpecifier.Right.PUT: "P", ContractSpecifier.Right.CALL: "C", } return ib_insync.Contract( symbol=specifier.symbol, secType=security_type_mapping[specifier.securityType], lastTradeDateOrContractMonth=specifier.lastTradeDateOrContractMonth, strike=float(specifier.strike) if specifier.strike else 0.0, right=right_mapping[specifier.right], multiplier=specifier.multiplier, exchange=specifier.exchange, currency=specifier.currency, localSymbol=specifier.localSymbol, primaryExchange=specifier.primaryExchange, tradingClass=specifier.tradingClass, includeExpired=specifier.includeExpired, )
def get_security_historical(self, contract_id, durationStr, barSizeSetting, whatToShow, useRTH, endDateTime='', updateDB=True): """ Note: cannot be used for expired options - alternative here (https://www.ivolatility.com/) """ assert self.connected, "Must connect to IBKR's Trader Workstation application before using this function" # create contract object uing the unique contract ID contract = ib_insync.Contract(conId=contract_id) self.client.qualifyContracts(contract) # use the IBKR API to get historical data bars = self.client.reqHistoricalData(contract, endDateTime=endDateTime, durationStr=durationStr, barSizeSetting=barSizeSetting, whatToShow=whatToShow, useRTH=useRTH) # convert to pandas dataframe df = ib_insync.util.df(bars) if updateDB: df['stock_id'] = contract.symbol df['ib_id'] = contract_id df = df.astype({"date": str}) df = df.drop(columns=['average', 'barCount']) if 'day' in barSizeSetting: price_history_table = 'Price_History_Day' elif 'hour' in barSizeSetting: price_history_table = 'Price_History_Hour' df['hour'] = df['date'].str.split(" ").str[1].str.split( ':').str[0] elif 'min' in barSizeSetting: price_history_table = 'Price_History_Minute' df['hour'] = df['date'].str.split(" ").str[1].str.split( ':').str[0] df['minute'] = df['date'].str.split(" ").str[1].str.split( ':').str[1] else: raise ValueError( "price data with bar size of {} cannot be inserted into the database" .format(barSizeSetting)) start_date = df['date'].min() end_date = df['date'].max() sql_execute = queries.sql_get_existing_records_dates.format( table=price_history_table, ib_id=contract_id, start_date=start_date, end_date=end_date) df['mid'] = (df['high'] + df['low']) / 2 dates_already_in_db = [ date[0] for date in queries.execute_sql(self.conn, sql_execute) ] df_new_records = df[~df['date'].isin(dates_already_in_db)] schema.insert_price_history(price_history_table, self.conn, df_new_records) return df
def branco_strategy1(ib, db, accid): try: cnt = ibsync.Stock('VXX', 'SMART', 'USD') ib.qualifyContracts(cnt) pricevxx = ib.reqTickers(cnt)[0].marketPrice() chains = ib.reqSecDefOptParams(cnt.symbol, '', cnt.secType, cnt.conId) chain = next(c for c in chains if c.tradingClass == cnt.symbol and c.exchange == cf.myprefexchange) lexps = [] for e in chain.expirations: lexps.append(int(e)) desiredexpiration = (date.today() + timedelta(days=15)).strftime('%Y%m%d') expiration = min(lexps, key=lambda x: abs(int(x) - int(desiredexpiration))) strikes = [ strike for strike in chain.strikes if (pricevxx * 0.9 < strike < pricevxx * 1.1) ] contracts = [ ibsync.Option('VXX', expiration, strike, "C", 'SMART', tradingClass='VXX') for strike in strikes ] ib.qualifyContracts(*contracts) greeks = [ ibutil.get_greeks(ib, contract).modelGreeks for contract in contracts ] deltas = [greek.delta for greek in list(filter(None, greeks))] ishort = int( min(range(len(deltas)), key=lambda i: abs(deltas[i] - 0.7))) ilong = int(min(range(len(deltas)), key=lambda i: abs(deltas[i] - 0.3))) #combo = ibsync.Contract() #combo.symbol = "VXX" #combo.secType = "BAG" #combo.exchange = "SMART" #combo.currency = "USD" #leg1 = ibsync.ComboLeg () #leg1.conId = contracts[ishort] #leg1.ratio = 1 #leg1.action = "SELL" #leg1.exchange = "SMART" #leg2 = ibsync.ComboLeg() #leg2.conId = contracts[ilong] #leg2.ratio = 1 #leg2.action = "BUY" #leg2.exchange = "SMART" #combo.comboLegs = [] #combo.comboLegs.append(leg1) #combo.comboLegs.append(leg2) #order = ibsync.order.LimitOrder("BUY", 1, 1, tif="GTC", transmit=False) #trade = ib.placeOrder(combo, order) combo = ibsync.Contract(symbol='VXX', secType='BAG', exchange='SMART', currency='USD', comboLegs=[ ibsync.ComboLeg(conId=contracts[ishort], ratio=1, action='SELL', exchange='SMART'), ibsync.ComboLeg(conId=contracts[ilong], ratio=1, action='BUY', exchange='SMART') ]) trade = tradelimitorder(ib, db, combo, 1, 1, "BRANCO_1") order = ibsync.LimitOrder(action='SELL', totalQuantity=1, lmtPrice=1, transmit=False, account=accid) trade = ib.placeOrder(combo, order) print(trade) except Exception as err: # error_handling(err) raise
log.debug(args) if args.debug: log.setLevel(logging.DEBUG) settings = yaml.load(open(args.settings,'r')) tickLogger = TickLogger(settings['dataRoot']) ib = ibis.IB() log.info('Connecting to IB') ib.connect('127.0.0.1', 4002, clientId=10) ib.pendingTickersEvent += tickLogger.tickHandler # subscribe to data contracts = [ibis.Contract(**sub) for sub in settings['subscriptions']] for contract in contracts: log.info('Subscribing to '+str(contract)) ib.reqMktData(contract, '', False, False) try: while True: ib.sleep(60) tickLogger.flush() except KeyboardInterrupt: log.info('Exiting')
elif q.lower() == "mavpaper2": rslt = ibutil.execute_query(mydb, sql + " connName = 'mavpaper2'") break elif q.lower() == "exit": sys.exit("Exit requested! ") else: q = input ("Unknown account! ") myib.connect(rslt[0][0], rslt[0][1], rslt[0][3]) myaccId = rslt[0][2] tickers= save_tickers('http://en.wikipedia.org/wiki/List_of_S%26P_500_companies') # tickers= save_tickers('https: // en.wikipedia.org / wiki / NASDAQ - 100 # Components') # tickers= save_tickers('https://www.nasdaq.com/quotes/nasdaq-100-stocks.aspx') for ticker in tickers: cnt = ibsync.Contract(symbol = ticker, secType = "STK", currency = "USD", exchange = "SMART") isopen = ibdb.positionisopen(mydb, myaccId, ticker ) if not myib.qualifyContracts(cnt) != [] and not isopen: try: breakout = requesthistoricaldata(cnt, 5, "Y", "1 week") except ValueError as e: print(e, cnt) continue if breakout > 0: opennewoption(myib, mydb, cnt, "SELL", "P", cf.myoptselldte, "5YHIGH") elif breakout < 0: opennewoption(myib, mydb, cnt, "SELL", "C", cf.myoptselldte, "5YLOW") except Exception as err: #error_handling(err) raise
def opennewoption(ib, cnt, opttype, optright, optdaystoexp): print("\n\t opennewoption") try: # agafem lastprice del underlying provinent de ticker lastpricestk = ib.reqTickers(cnt)[0].marketPrice() # busquem la cadena d'opcions del underlying chains = ib.reqSecDefOptParams(cnt.symbol, '', cnt.secType, cnt.conId) chain = next(c for c in chains if c.tradingClass == cnt.symbol and c.exchange == 'SMART') # separem strikes i expiracions (tenir en compte que strikes i expiracions estan en forma de Set, no de List lstrikes = chain.strikes # busquem el strike que més s'acosta a lastpricestk orderstrike = min(lstrikes, key=lambda x: abs(int(x) - lastpricestk)) # busquem la expiration que més s'acosta a desiredexpiration lexps = [] for e in chain.expirations: lexps.append(int(e)) desiredexpiration = date.today() + timedelta(days=optdaystoexp) desiredexpiration = int( str(desiredexpiration)[0:4] + str(desiredexpiration)[5:7] + str(desiredexpiration)[8:10]) orderexp = min(lexps, key=lambda x: abs(int(x) - desiredexpiration)) # preparem el nou trade: definim i qualifiquem la nova opció optcnt = ibsync.Contract() optcnt.symbol = cnt.symbol optcnt.strike = orderstrike optcnt.secType = "OPT" optcnt.exchange = "SMART" optcnt.currency = cnt.currency optcnt.right = optright optcnt.lastTradeDateOrContractMonth = orderexp # no tots els strikes possibles (entre ells potser el ja triat) són vàlids. # si el strike triat no és vàlid en busquem un que sigui vàlid apujant (i baixant) el strike en 0.5 # fins a trobar un que sigui acceptat. Això pot provocar que ens allunyem del ATM, però no hi ha altra solució ct = 0 while ib.qualifyContracts(optcnt) == [] and ct < 11: optcnt.strike = orderstrike = int(orderstrike + 0.5 * (optright == "C") - 0.5 * (optright == "P")) ct += 1 # busquem el preu al que cotitza la nova opció de la que obrirem contracte topt = ib.reqTickers(optcnt) lastpriceopt = topt[0].marketPrice() # fem un reqN¡MktData per obtenir (hopefully) els Greeks opttkr = ib.reqMktData(optcnt, '', False, False) # això torna un objecte Ticker l = 0 while (opttkr.lastGreeks == None ) and l < 5: # mini-bucle per esperar que es rebin els Greeks opttkr = ib.reqMktData(optcnt, '', False, False) ib.sleep(5) l += 1 # definim la quantitat = (Capital màxim)/(100*preu acció*Delta) # en cas que la delta torni buida, usem 0.5 (de moment agafem opcions AtTheMoney igualment) if (opttkr.lastGreeks.delta is not None): qty = (1 - 2 * -(opttype == "SELL")) * round( ibconfig.mymaxposition / (100 * lastpricestk * abs(opttkr.lastGreeks.delta))) else: qty = (1 - 2 * (opttype == "SELL")) * round(ibconfig.mymaxposition / (100 * lastpricestk * 0.5)) print("symbol ", optcnt.symbol, "lastpricestk ", lastpricestk, "desiredstrike", lastpricestk, "orderstrike ", orderstrike, "desiredexpiration", desiredexpiration, "orderexp ", orderexp, "quantity", qty, "conId", optcnt.conId, "price", lastpriceopt) if lastpriceopt == lastpriceopt: #checks if nan return tradelimitorder(ib, optcnt, qty, lastpriceopt) else: return None except Exception as err: error_handling(err) raise
def opendefensiveposition(ib, cnt, pos): try: print("opendefensiveposition") # creem objectes tupus contracte stkcnt = ibsync.Contract() # el underlying de la opció optcnt1 = ibsync.Contract() # la opció que hi ha al portfolio optcnt2 = ibsync.Contract() # la potencial nova opció que es crearà # composem el contracte del underlying de la opció analitzada # stkcnt = Stock(cnt.symbol, "SMART", cnt.currency) stkcnt.symbol = cnt.symbol stkcnt.currency = cnt.currency stkcnt.secType = "STK" stkcnt.exchange = "SMART" ib.qualifyContracts(stkcnt) print("defensiveposition de: ", stkcnt) # composem el contracte de la opció analitzada optcnt1.conId = pos.conId ib.qualifyContracts(optcnt1) # composem la data d'expiració que és la mateixa tant per la opció original (optcnt1) com la nova defensiva (optcnt2) dateexpiration = str(optcnt1.lastTradeDateOrContractMonth)[0:4] + str( optcnt1.lastTradeDateOrContractMonth)[4:6] + str( optcnt1.lastTradeDateOrContractMonth)[6:8] # agafem lastprice del underlying provinent de ticker tstk = ib.reqTickers(stkcnt) topt1 = ib.reqTickers(optcnt1) lastpricestk = tstk[0].marketPrice() lastpriceopt1 = topt1[0].marketPrice() ib.sleep(1) # busquem la cadena d'opcions del underlying chains = ib.reqSecDefOptParams(stkcnt.symbol, '', stkcnt.secType, stkcnt.conId) chain = next( c for c in chains if c.tradingClass == stkcnt.symbol and c.exchange == 'SMART') # separem strikes i expiracions lexps = [] lstrikes = [] lexps = chain.expirations lstrikes = chain.strikes myList = lstrikes lastpricestk = int(lastpricestk) # calculem la distància entre el preu del underlying ara i el strike de la opció venuda que estem analitzant strikedistance = abs(optcnt1.strike - lastpricestk) # busquem l'strike que més s'acosta al del preu actual del underlying orderstrike = min(lstrikes, key=lambda x: int(abs(int(x) - lastpricestk))) # preparem el nou trade: si era un call ara un put...i al inreves if optcnt1.right == "C": opt2right = "P" else: opt2right = "C" # preparem el nou trade: qualifiquem la nova opció compensatoria optcnt2.symbol = optcnt1.symbol optcnt2.strike = orderstrike optcnt2.secType = optcnt1.secType optcnt2.exchange = "SMART" optcnt2.currency = optcnt1.currency optcnt2.right = opt2right optcnt2.lastTradeDateOrContractMonth = dateexpiration ib.qualifyContracts(optcnt2) print("optcon2", optcnt2) # busquem el preu al que cotitza la nova opció compensatoria topt2 = ib.reqTickers(optcnt2) lastpriceopt2bis = (topt2[0].bid + topt2[0].ask) / 2 # lastprice = formatPrice(lastprice, 2) lastpriceopt2 = topt2[0].marketPrice() ib.sleep(1) # executem la ordre print("opendefensiveposition - ", optcnt2, pos.shares, lastpriceopt2, pos.conId) tradelimitorder(ib, optcnt2, pos.shares, lastpriceopt2) except Exception as err: error_handling(err) raise
def processopenpositions(ib, db, vAccId): print("\nprocessopenpositions") try: # llegim posicions obertes de la base de dades query = "SELECT pId, pExecId, pAccId, pConId, pDate, pType, pMultiplier, pShares, pInitialPrice,pInitialValue, pClosingPrice, pClosingValue," \ " pClosingDate, pClosingId, pPNL, pCommission, pLiquidation, pActive" \ " FROM positions LEFT JOIN contracts ON positions.pConId = contracts.kConId" \ " WHERE pAccId = '" + vAccId + "' AND pActive = 1" rst = execute_query(db, query, values=None) # definim namedtuple "positions" per a processar posicions obertes positions = namedtuple( "positions", "Id execId accId conId \ date type multiplier shares initialPrice initialValue closingPrice \ closingValue closingDate closingId PNL commission liquidation \ active") # passem les execucions obertes en forma de namedtuple a la llista "openpos" openpos = [] for i in range(len(rst)): position = positions(Id=rst[i][0], execId=rst[i][1], accId=rst[i][2], conId=rst[i][3], date=rst[i][4], type=rst[i][5], multiplier=rst[i][6], shares=rst[i][7], initialPrice=rst[i][8], initialValue=rst[i][9], closingPrice=rst[i][10], closingValue=rst[i][11], closingDate=rst[i][12], closingId=rst[i][13], PNL=rst[i][14], commission=rst[i][15], liquidation=rst[i][16], active=rst[i][17]) openpos.append(position) # llegim "openpos" en forma de loop per a decidir què fer amb cada execució oberta pctProfitList = [] for pos in openpos: # creem un objecte Contract cnt = ibsync.Contract() # fem una instancia de contract amb el contracte llegit del query de trades oberts de la db trades cnt.conId = pos.conId ib.qualifyContracts(cnt) pfl = ib.portfolio() # obtenim i formategem data expiració dateexpiration = str(cnt.lastTradeDateOrContractMonth)[0:4] + str( cnt.lastTradeDateOrContractMonth)[4:6] + str( cnt.lastTradeDateOrContractMonth)[6:8] # agafem lastprice provinent de portfolio lastprice = 0 for f in pfl: if pos.conId == f.contract.conId: lastprice = f.marketPrice # lastprice = f.marketValue # demanem dades a traves de reqMktData # m_data = ib.reqMktData(cnt) # while m_data.last != m_data.last: ib.sleep(0.01) # Wait until data is in. # ib.cancelMktData(cnt) # print("m_data ",m_data.last) avgcost = float(pos.initialPrice) vshares = pos.shares # calculem pctprofitnow (el pnl de la posició) if vshares < 0: pctprofitnow = (1 - (lastprice / avgcost)) * 100 else: pctprofitnow = ((lastprice / avgcost) - 1) * 100 print(cnt.symbol, " ", vshares, "lastprice ", lastprice, "avgcost", avgcost, "pctprofitnow ", pctprofitnow) # calculem percentatge temps passat entre apertura posició i expiració per a posicions d'opcions pctpostimeelapsed = 0 if cnt.secType == "OPT": dateentry = str(pos.date)[0:4] + str(pos.date)[5:7] + str( pos.date)[8:10] datetoday = datetime.datetime.now().strftime("%Y%m%d") datedifffromentry = diffdays datedifffromentry = diffdays(dateentry, dateexpiration) datedifffromtoday = diffdays(datetoday, dateexpiration) pctpostimeelapsed = int( (1 - datedifffromtoday / datedifffromentry) * 100) # d'acord amb els paràmetres calculats decidim si es fa un trade o no a la funció "allowtrade" # allowtrade = allowTrade(pctpostimeelapsed, pctprofitnow) allowtrade = allowTrade(pctpostimeelapsed, pctprofitnow, cnt.secType) # allowtrade = 0 pctProfitList.append([ cnt.symbol, pos.shares, cnt.right, cnt.strike, pos.initialPrice, lastprice, int(pctprofitnow), pctpostimeelapsed, allowtrade ]) # allowtrade = 1 tancar posició per recollida de beneficis, allowtrade = 2 fem un trade defensio de la posició price = 0 if allowtrade == 1: if pos.shares < 0: ordertype = 'BUY' else: ordertype = 'SELL' # Configurem preu operació if ordertype == "BUY" and cnt.secType == "OPT": # price = ((avgcost * ((100 - pctprofitnow)) / 100)) / 100 price = avgcost * (1 - pctprofitnow / 100) elif ordertype == "SELL" and cnt.secType == "OPT": # price = (avgcost * (1 + (pctprofitnow / 100))) / 100 price = avgcost * (1 + pctprofitnow / 100) fmtprice = formatPrice(price, 2) print("Close Position: \t", cnt, "\t", ordertype, "\t", fmtprice) tradelimitorder(ib, cnt, -vshares, fmtprice) elif allowtrade == 2: # obrim posició defensiva opendefensiveposition(ib, cnt, pos) elif allowtrade == 3: if pos.shares < 0: ordertype = 'BUY' else: ordertype = 'SELL' # Configurem preu operació if ordertype == "BUY": price = lastprice # price = avgcost * (1 - pctprofitnow / 100) elif ordertype == "SELL": price = lastprice # price = avgcost * (1 + pctprofitnow / 100) fmtprice = formatPrice(price, 2) print("Close Position: \t", cnt, "\t", ordertype, "\t", fmtprice) tradelimitorder(ib, cnt, -vshares, fmtprice) elif allowtrade == 4: if pos.shares < 0: ordertype = 'BUY' else: ordertype = 'SELL' # Configurem preu operació if ordertype == "BUY": price = lastprice # price = avgcost * (1 - pctprofitnow / 100) elif ordertype == "SELL": price = lastprice # price = avgcost * (1 + pctprofitnow / 100) fmtprice = formatPrice(price, 2) print("Close Position: \t", cnt, "\t", ordertype, "\t", fmtprice) tradelimitorder(ib, cnt, -vshares, fmtprice) elif allowtrade == "8888": pass else: pass except Exception as err: error_handling(err) raise