Placing options order - python

I am new to python and programming but I am learning. I am trying to send an order through python for options to TWS. I keep getting this error message
"Server Error: Server Response:
error, Traceback (most recent
call last):"
I tried to put an order for stock and it went through but not for options
def create_contract(a,b,c,d):
contract = Contract()
contract.symbol = '%a'
contract.secType = "OPT"
contract.exchange = "SMART"
contract.order_exchange = "SMART"
contract.currency = "USD"
contract.ContractMonth = b
contract.strike = c
contract.right = '%d'
contract.multiplier = "100"
return contract
def create_order(order_type, quantity, action):
order = Order()
order.m_orderType = order_type
order.m_totalQuantity = quantity
order.m_action = action
return order
if __name__ == "__main__":
tws_conn = Connection.create("127.0.0.1", port=7495)
tws_conn.connect()
tws_conn.register(error_handler, 'Error')
tws_conn.registerAll(reply_handler)
order_id = 1
goog_contract = create_contract(tic,hup.cell(2,3).value,hup.cell(2,4).value,hup.cell(2,13).value)
goog_order = create_order('MKT', 1, 'BUY')
tws_conn.placeOrder(order_id, goog_contract, goog_order)
I want to see the option orders goes through TWS. I also would love to see some proper example on how the placeorder parameter should have.

from ib_insync import *
util.startLoop()
ib=IB()
ib.connect("127.0.0.1", 7497, clientId=13)
contract=Option("SPY","20191016", 280,"P","SMART")
ib.qualifyContracts(contract)
order=MarketOrder("Buy",2)
trade=ib.placeOrder(contract,order)
trade
this code will allow. you to buy 2 puts on the "spy" at a 280 strike expiring October 19 2019

It looks like you're using IBPy or a third party wrapper of an IB API? You may want to consider instead using the native Python API from IB, or ib_insync.
If you can place an order for a stock but not an option, the problem is likely in the way the option contract is defined (assuming your paper account has the necessary permissions). There are examples of defining options in the native IB Python API at:
http://interactivebrokers.github.io/tws-api/basic_contracts.html#opt
To say which parameter is incorrect you would have to show the values of a,b,c,d.
You may want to also enable API logging in TWS as described at:
http://interactivebrokers.github.io/tws-api/support.html#tws_logs
for troubleshooting purposes.

Related

Python Binance Futures Take Profit and Stop Loss order API Error 2021 Order would immediately trigger

I have written a trading bot working on futures account for margin trading. The piece of code that I shared below worked fine for just one time. Then it started to give the following error:
APIError(code=-2021): Order would immediately trigger
The problem is when I copy and paste this piece of code(part related to open position and give take profit and stop loss orders) to a new file and run it, it works fine but gives an error in the bot. I couldn't find the cause of the problem.
if currentdiffer > 0:
buy_order = client.futures_create_order(symbol='SOLBUSD',
side='BUY',
type ='MARKET',
quantity = qty,
positionSide='LONG')
poisiton = "LONG"
stopprice = currentprice - (value*1.2)
takeprofit = currentprice + (value*1.2)
stopprice = round(stopprice,2)
takeprofit = round(takeprofit,2)
print("Take profit : ", takeprofit)
print("Stop price : ", stopprice)
tp_order = client.futures_create_order(symbol='SOLBUSD',
side='SELL',
positionSide='LONG',
type ='TAKE_PROFIT_MARKET',
timeInForce='GTE_GTC',
quantity = qty,
stopPrice=stopprice,
workingType='MARK_PRICE'
)
sl_order = client.futures_create_order(symbol='SOLBUSD',
side='SELL',
positionSide='LONG',
type ='STOP_MARKET',
timeInForce='GTE_GTC',
quantity = qty,
stopPrice=takeprofit,
workingType='MARK_PRICE'
)
Seems like you messed up with the parameter that you send
Check the API Docs. It's all there
For TRAILING_STOP_MARKET, if you got such error code.
{"code": -2021, "msg": "Order would immediately trigger."}
means that the parameters you send do not meet the following requirements:
BUY: activationPrice should be smaller than latest price.
SELL: activationPrice should be larger than latest price.
https://binance-docs.github.io/apidocs/futures/en/#new-order-trade

last price for multiple symbols

I'm trying to get the last price for multiple symbols using ib_insync package, but I don't know how to pass the ib object to the function, and the last price returned from the function is nan. This will be single threaded, so I can use a global variable for ib.
def last_live_price(ib,symbol_in,exchange_in,currency_in):
contract=Stock(symbol=symbol_in,exchange=exchange_in,currency=currency_in)
last_live=ib.reqMktData(contract, genericTickList='', snapshot=True, regulatorySnapshot=False,mktDataOptions=None)
time.sleep(5)
last=last_live.last
return(last)
util.startLoop() # uncomment this line when in a notebook or spynder
ib = IB()
ib.connect('127.0.0.1', 7496,clientId=26)
d = {'symbol':['700', '9988', '2318', '386'],
'exchange':['SEHK','SEHK','SEHK','SEHK'],
'currency':['HKD','HKD','HKD','HKD']
}
hk = pd.DataFrame(data=d)
#how should ib object be passed to the function?
hk['last']=hk.apply(lambda x: ib,last_live_price(symbol_in=x['symbol'],
exchange_in=x['exchange'],
currency_in=x['currency']),axis=1)
#how should ib object be passed to the function?
test_last=last_live_price(ib=ib,symbol_in='CBA',exchange_in='ASX',currency_in='AUD')
This code is working: time.sleep(x) causes a problem so replace it with ib.sleep(x), and getting the full contract via ib.qualifyContracts(contract) is good practice.
def last_live_price(symbol_in,exchange_in,currency_in):
contract=Stock(symbol=symbol_in,exchange=exchange_in,currency=currency_in)
ib.qualifyContracts(contract)
ib.sleep(5)
last_live=ib.reqMktData(contract, genericTickList='', snapshot=True, regulatorySnapshot=False,mktDataOptions=None)
ib.sleep(5)
last=last_live.last
return(last)
d = {'symbol':['NAB', 'CBA', 'ANZ', 'ORG'],
'exchange':['ASX','ASX','ASX','ASX'],
'currency':['AUD','AUD','AUD','AUD'],
'last':[None,None,None,None]
}
stocks = pd.DataFrame(data=d)
stocks['last']=stocks.apply(lambda x: last_live_price(symbol_in=x['symbol'],
exchange_in=x['exchange'],
currency_in=x['currency']),axis=1)

Calculating price of BSC token with Web3 and Python

I'm building a tool with web3 and python that needs to quickly and accurately get prices of tokens on Binance Smart Chain via PancakeSwap.
The tool gathers information about BSC tokens, price, liquidity etc so I can further analyse rugpulls.
In the following code it is supplied with a contract address and it needs to supply the current price per token in BNB. It however glitches alot and does not give me the correct price and I cannot figure out whats wrong. Code is below.
from web3 import Web3
web3 = Web3(Web3.WebsocketProvider('wss://speedy-nodes-nyc.moralis.io/b51e035eb24e1e81cc144788/bsc/mainnet/ws'))
tokenPriceABI = 'Token Price ABI'
def getTokenPrice(tokenAddress):
BNBTokenAddress = Web3.toChecksumAddress("0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c") # BNB
amountOut = None#
#tokenAddress = Web3.toChecksumAddress(tokenAddress)
tokenRouter = web3_sell.eth.contract(address=tokenAddress, abi=tokenPriceABI)
router = web3_sell.eth.contract(address=Web3.toChecksumAddress("0x10ed43c718714eb63d5aa57b78b54704e256024e"), abi=pancakeABI)
amountIn = web3_sell.toWei(1, 'ether')
amountOut = router.functions.getAmountsOut(amountIn, [tokenAddress, BNBTokenAddress]).call()
amountOut = web3_sell.fromWei(amountOut[1], 'ether')
return amountOut
tokenAddress = input("Enter token address: ")
tokenAddress = Web3.toChecksumAddress(tokenAddress)
priceInBnb = getTokenPrice(tokenAddress)
print(priceInBnb)
Is anyone able to help?
Thanks.
so what you are doing is you are trying to get the wrong value.
the getamountsout doesn't give you you the price. you need to call the getpair from the pancakeswap factory address with your two tokens as parameters.(0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73) docs for the getpair function
then you get a contract address back from which you can call the getreserves function (docs for this contract) from which you get 3 values (_reserve0, _reserve1, _blockTimestampLast) where you divide the first by the second or the second by the first depending on which way you want the price

Python multiple requests with single code

I am using the IB API to retrieve historical stock data, and I would like my code to run multiple times with different variables (different stocks and timeframes).
Currently I am using the following code:
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
def print_to_file(*args):
with open('text6.txt', 'a') as fh:
fh.write(' '.join(map(str,args)))
fh.write('\n')
print = print_to_file
class TestApp(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
Layout = "{!s:1} {!s:2} {!s:3} {!s:4} {!s:5} {!s:6} {!s:7} {!s:8} {!s:8} '\n'"
print(Layout.format("Ticker;", "Date;", "None;", "Time;", "Open;", "High;", "Low;", "Close;", "Volume"))
def historicalData(self, reqId, bar):
print("AAPL", ";", bar.date.replace(' ', '; '), ";", bar.open, ";", bar.high, ";", bar.low, ";", bar.close, ";", bar.volume)
def main():
app = TestApp()
app.connect("127.0.0.1", 7497, 0)
contract = Contract ()
contract.symbol = "AAPL"
contract.secType = "STK"
contract.exchange = "SMART"
contract.currency = "USD"
contract.primaryExchange = "NASDAQ"
app.reqHistoricalData(0, contract, "20180201 10:00:00", "1 M", "1 min", "TRADES", 0, 1, False, [])
app.run()
if __name__ == "__main__":
main()
I have tried the following for multiple stocks:
contract.symbol = ["AAPL", "GOOG"]
But this gives me the error message:
No security definition has been found for the request
And using the following code for time & date:
app.reqHistoricalData(0, contract, ["20180201 10:00:00", "20180301 10:00:00"], "1 M", "1 min", "TRADES", 0, 1, False, [])
Gives me the error message:
Error validating request:-'bP' : cause - Historical data query end date/time string [['20180201 10:00:00', '20180301 10:00:00']] is invalid. Format is 'YYYYMMDD{SPACE}hh:mm:ss[{SPACE}TMZ]'.
Basically I would like this .py file to run multiple requests in a single run, using multiple variables so that I can receive data for multiple stocks in a single run.
Could anybody here help me to achieve this?
Thanks!
You can create a class that derives from the Contract class in order to create multiple Contract objects at one time. Then, make a loop that passes your Contract objects into the client in order to get the data. What you are currently doing is pretty far off from any implementation that would actually work. Check out this blog for help with the set-up of a working system -> https://qoppac.blogspot.com/2017/03/interactive-brokers-native-python-api.html
As far as the contract class, look at the relevant parameters in the documentation and create a class as necessary. Here is an example of my futures class:
class IBFutures(Contract):
def __init__(self, symbol:str, exchange:str, secType:str,
currency = 'USD', localSymbol = ""):
Contract.__init__(self)
self.symbol = symbol
self.secType = secType
self.exchange = exchange
self.currency = currency
self.localSymbol = localSymbol
Then, in your client object, make a function similar to this:
def getHistoricalData(self, contracts, durationStr="3 D", barSizeSetting="30 mins", whatToShow = "TRADES"):
"""
Returns historical prices for a contract, up to today
ibcontract is a Contract
:returns list of prices in 4 tuples: Open high low close volume
"""
defaultid = 80
prices = {}
for symbol in contracts:
defaultid += 1 # update defaultid
# Make a place to store the data we're going to return
historic_data_queue = finishableQueue(self.init_historicprices(defaultid))
# Should endDateTime be set to 9:00AM EST??
# Request some historical data. Native method in EClient
self.reqHistoricalData(reqId=defaultid, contract = contracts[symbol],
endDateTime=datetime.datetime.today().strftime("%Y%m%d %H:%M:%S"),
durationStr=durationStr, barSizeSetting=barSizeSetting,
whatToShow=whatToShow, useRTH=0, formatDate=1,
keepUpToDate=False, chartOptions=[])
# Wait until we get a completed data, an error, or time-out
MAX_WAIT_SECONDS = 30
logger.info("Getting %s historical data from the server..." % symbol)
historic_data = historic_data_queue.get(timeout=MAX_WAIT_SECONDS)
clean_data = cleanPrice(data=historic_data)
prices[symbol] = clean_data
if historic_data_queue.timed_out():
logger.info("Exceeded maximum wait for wrapper to confirm finished")
self.cancelHistoricalData(defaultid)
logger.info("Prices retrieved for %d contracts" % len(prices))
return prices

How to get the specific token balance available at a give ETH address using web3.py

I am getting started with web.py. I have a requirement where I need to get the available token balance at a given ETH address(this address is not the contract owner), going through the docs I stumble upon the following functiion :
https://web3py.readthedocs.io/en/stable/contracts.html#web3.contract.ContractFunction.call
token_contract.functions.myBalance().call({'from': web3.eth.accounts[1]})
so on the above lines, I wrote this :
from web3 import HTTPProvider, Web3
import requests
w3 = Web3(HTTPProvider('https://ropsten.infura.io/RPw9nHRS7Ue47RaKVvHM'))
url_eth = "https://api.etherscan.io/api"
contract_address = '0x0CdCdA4E7FCDD461Ba82B61cBc4163E1022f22e4'
API_ENDPOINT = url_eth+"?module=contract&action=getabi&address="+str(contract_address)
r = requests.get(url = API_ENDPOINT)
response = r.json()
instance = w3.eth.contract(
address=Web3.toChecksumAddress(contract_address),
abi = response["result"]
)
send_address = "0xF35A192475527f80EfcfeE5040C8B5BBB596F69A"
balance = instance.functions.balance_of.call({'from':send_address})
#balnce = instance.functions.myBalance.call({'from':send_address})
print("----------------------",balance)
I get the following error :
"Are you sure you provided the correct contract abi?"
web3.exceptions.MismatchedABI: ("The function 'balance_of' was not foundin this contract's abi. ", 'Are you sure you provided the correct contract abi?')
**Update ** I got rid of the above exception, now I'm getting the following exception :
send_address = "0xF35A192475527f80EfcfeE5040C8B5BBB596F69A"
balance = instance.functions.balanceOf.call(send_address)
#Error :
call_transaction = dict(**transaction)
TypeError: type object argument after ** must be a mapping, not str
If I try this :
send_address = "0xF35A192475527f80EfcfeE5040C8B5BBB596F69A"
balance = instance.functions.balanceOf.call({'from':send_address})
#Error:
AttributeError: 'balanceOf' object has no attribute 'args'
In the last code sample try to modify the second line to look like this: balance = instance.functions.balanceOf().call({'from':send_address}). The parenthesis after balance of are the arguments you are passing to the solidity function.
you have to see if the contract has the function "balance_of". At the time of executing
balance = instance.functions.balanceOf.call(send_address)
You are executing the balance_of function of the contract, if the contract does not have that function it gives the error
This works for sure as of today:
send_address = "0xF35A192475527f80EfcfeE5040C8B5BBB596F69A"
balance = instance.functions.balanceOf(send_address).call()

Categories