import aiohttp from pprint import pprint from decimal import Decimal as D import dill as pickle import time import copy import os import json import asyncio from utils import * from piecewise import * NADEX_ROOT = "https://trade.nadex.com/iDeal" if not DEMO else "https://demo-trade.nadex.com/iDeal" NADEX_UPD = "https://upd.nadex.com" if not DEMO else "https://demo-upd.nadex.com" NADEX_AUTH = read_auth("nadex") if not DEMO else read_auth("nadex_demo") NADEX_SESSION_FILE = ".nadex_session" COMMON_HEADERS = { "accept": "application/json; charset=UTF-8", "accept-encoding": "gzip, deflate, br", "accept-language": "en-US,en;q=0.9", "content-type": "application/json; charset=UTF-8", "origin": "https://platform.nadex.com", "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36", "x-device-user-agent": "vendor=IG | applicationType=Nadex | platform=web | deviceType=phone | version=0.853.0+6a6399d3", } class NadexSession: def __init__(self, s): self.s = s def __repr__(self): return "nadex" async def login(self): self.s.headers.clear() self.s.headers.update(COMMON_HEADERS) self.s.cookie_jar.clear() if os.path.exists(NADEX_SESSION_FILE): with open(NADEX_SESSION_FILE, 'rb') as f: self.token = pickle.load(f) else: print("doing new login") async with self.s.post( NADEX_ROOT + "/v2/security/authenticate", json = NADEX_AUTH, ) as resp: self.token = resp.headers["x-security-token"] print(self.token) print() with open(NADEX_SESSION_FILE, 'wb') as f: pickle.dump(self.token, f) self.s.headers["x-security-token"] = self.token async def get_marketinfo(self, mid, try_relog=True): async with self.s.get( NADEX_ROOT + "/markets/navigation/"+str(mid), ) as resp: if resp.status==401 and try_relog: if os.path.exists(NADEX_SESSION_FILE): os.remove(NADEX_SESSION_FILE) await self.login() return await self.get_marketinfo(mid, False) return await resp.json() async def execute_order(self, mid, p, s, buy): async with self.s.post( f"{NADEX_ROOT}/orders/workingorders/dma", json = { "direction": "+" if buy else "-", "epic": mid, "lsServerName": NADEX_UPD+":443", "orderLevel": str(D(p)/100), "orderSize": str(s), "orderType": "MarketLimit", "pricePreference": None, "timeInForce": "GoodTillCancelled", "timeStamp": int(time.time()), "tolerance": None, }, ) as resp: pprint("nadex order") pprint(resp) pprint(await resp.json()) pprint("") async def init_lightstreamer(self, marketids): proc = await asyncio.create_subprocess_exec( "node", "nadex_ws.js", stdin=asyncio.subprocess.PIPE, stdout=asyncio.subprocess.PIPE, ) proc.stdin.write(json.dumps({ "username": NADEX_AUTH["username"].upper(), "security_token": self.token, "marketids": marketids, "servername": NADEX_UPD, }).encode()) await proc.stdin.drain() proc.stdin.close() await proc.stdin.wait_closed() return proc async def orderbook_stream(self, marketid): breaks = {} for market in (await self.get_marketinfo(marketid))["markets"]: low = cents(market["instrumentName"].split(">")[1].split()[0]) low += 1 breaks[market["epic"]] = low proc = await self.init_lightstreamer([*breaks.keys()]) book = {} async for line in proc.stdout: data = json.loads(line.strip().decode()) epic = data["id"] br = breaks[epic] asks = [] bids = [] for p, s in data["asks"]: p = cents(p) asks.append((conv_lim_pc(br, None).add_conditional(-100) + (-p - 100), s, p)) for p, s in data["bids"]: p = cents(p) bids.append(((-conv_lim_pc(br, None)).add_conditional(-100) + (p - 100), s, p)) book[epic] = Digital( low = br, high = None, bids = bids, asks = asks, exchange = self, market_id = epic, ) yield [*book.values()] async def main(): async with aiohttp.ClientSession() as rs: s = NadexSession(rs) await s.login() await s.execute_order("NB.D.U500.OPT-1-16-04Nov22.IP", 600, 1, True) # async for book in s.orderbook_stream(160809): # pprint(book) # pass if __name__=="__main__": asyncio.run(main())