def reconnect(rpc): """ create a fresh websocket connection to a random node """ try: rpc.close() except: pass while True: try: # create a connection to a dex node storage = {"mean_ping": 1} nodes = race_read_json("nodes.txt") random.shuffle(nodes) # return rpc, handshake_latency, handshake_max rpc, _, _ = wss_handshake(storage, nodes[0]) # make sure its a fast connection, else recursion begin = time.time() _ = rpc_last(rpc, {"asset": "BTS", "currency": "BTC"}) break except Exception as error: print(trace(error)) pass if begin - time.time() > 0.4: print(nodes[0], "TOO SLOW") reconnect(rpc) return rpc
def cancel_all_markets(account_name, wif): """ clone of main for importation as a module within botscript acts in triplicate in case first two nodes report bad data """ nodes = race_read_json(doc="nodes.txt") for _ in range(3): rpc = reconnect(None) account_id = rpc_account_id(rpc, account_name) orders = rpc_open_orders(rpc, account_name) orders = list(set(orders)) orders.sort() if orders: order = { "edicts": [ { "op": "cancel", "ids": orders }, ], "header": { "asset_id": "1.3.1", # placeholder "currency_id": "1.3.1", # placeholder "asset_precision": 5, # placeholder "currency_precision": 5, # placeholder "account_id": account_id, "account_name": account_name, "wif": wif, }, "nodes": nodes, } broker(order)
def aggregate(exchanges, api): """ post process data from all exchanges to extract medians and means """ data = {} for exchange in exchanges: try: doc = exchange + api["pair"] + ".txt" print("reading", doc) json_data = race_read_json(doc) if json_data: data[exchange] = json_data except Exception as error: print(error.args) prices = [] for key, val in data.items(): try: if int(time.time()) - val["time"] < 300: prices.append(val["last"]) except Exception as error: print(error.args) median_price = median(prices) mean_price = sum(prices) / len(prices) return { "mean": mean_price, "median": median_price, "data": data, }
def refresh_forex_rates(): """ make process wrapped external calls; IPC via text pipe """ methods = [ aastock, # DARKWEB API; MORNINGSTAR (GOOGLE FINANCE) BACKDOOR barchart, # KEYED bitcoinaverage, # MAY ADD CAPTCHA; HEADER REQUIRED; CLOUDFARE SPOOFING bloomberg, # MAY ADD CAPTCHA; HEADER REQUIRED; CLOUDFARE SPOOFING currencyconverter, # KEYED, NOT COMPATIBLE WITH VPN / DYNAMIC IP currencyme, # DARKWEB API duckduckgo, # XML SCRAPING, XE BACKDOOR exchangeratewidget, # XML SCRAPING finviz, # DARKWEB API fixerio, # KEYED forexrates, # XML SCRAPING forextime, # DARKWEB API freeforex, # FREE API fscapi, # KEYED fxcm, # CLOUDFARE SPOOFING; HEADER REQUIRED; ALMOST JSON RESPONSE fxempire1, # XIGNITE BACKDOOR; HEADER REQUIRED; CLOUDFARE SPOOFING fxempire2, # TRADINGVIEW BACKDOOR fxmarket, # KEYED fxrate, # XML SCRAPING ino, # DARKWEB API investing, # CLOUDFARE SPOOFING, XML SCRAPING liveusd, # DARKWEB API oanda, # DARKWEB API; RC4 ECRYPTION OF LATIN ENCODING openexchangerates, # KEYED reuters, # REFINITIV BACKDOOR, DARKWEB API wocu, # XML SCRAPING wsj, # MARKETWATCH BACKDOOR, DARKWEB API yahoo, # YAHOO FINANCE V7 DARKWEB API ] # initialize each external call method as a process processes = {} for method in methods: site = method.__name__ race_write(f"{site}_forex.txt", {}) processes[site] = Process(target=method, args=(site, )) processes[site].daemon = False processes[site].start() # FIXME: FOR DEPLOYMENT ON LOW COST WEB HOSTING SERVICES # FIXME: ALTERNATIVE RAM SAVINGS 0.5GB, WITH ADDED EXECUTION TIME OF 5 MINUTES # FIXME: **INCLUDE** NEXT 3 LINES FOR LOW RAM ALTERNATIVE # processes[site].join(TIMEOUT) # processes[site].terminate() # time.sleep(5) # FIXME: **EXCLUDE** NEXT 4 LINES FOR LOW RAM ALTERNATIVE for site in processes.keys(): processes[site].join(TIMEOUT) for site in processes.keys(): processes[site].terminate() # read the text pipe ipc results of each process sources = {} for site in processes.keys(): sources[site] = race_read_json(f"{site}_forex.txt") return sources
def main(): """ primary event circuit """ nodes = race_read_json(doc="nodes.txt") print("\033c") print("\n\nCANCEL ALL OPEN ORDERS IN ALL DEX MARKETS\n\n") account_name = input("\n Bitshares" + it("yellow", " AGENT NAME:\n\n ")) rpc = reconnect(None) account_id = rpc_account_id(rpc, account_name) print("\n\n", account_name, account_id, "\n\n") orders = rpc_open_orders(rpc, account_name) orders = list(set(orders)) orders.sort() if orders: print(orders, "\n\n") user_resp = input("proceed to cancel these orders? y/n ").lower() if user_resp == "y": wif = getpass("\n Bitshares" + it("yellow", " AGENT WIF:\n ")) print(" *****************") time.sleep(2) order = { "edicts": [ { "op": "cancel", "ids": orders }, ], "header": { "asset_id": "1.3.1", # placeholder "currency_id": "1.3.1", # placeholder "asset_precision": 5, # placeholder "currency_precision": 5, # placeholder "account_id": account_id, "account_name": account_name, "wif": wif, }, "nodes": nodes, } broker(order) else: print("\n\nThere are no open orders to cancel\n\n")
def refresh_forex_rates(): """ make process wrapped external calls; IPC via text pipe """ methods = [ aastock, # DARKWEB API; MORNINGSTAR (GOOGLE FINANCE) BACKDOOR bloomberg, # MAY ADD CAPTCHA; HEADER REQUIRED; CLOUDFARE SPOOFING currencyme, # DARKWEB API duckduckgo, # XML SCRAPING, XE BACKDOOR exchangeratewidget, # XML SCRAPING forexrates, # XML SCRAPING forextime, # DARKWEB API freeforex, # FREE API fxcm, # CLOUDFARE SPOOFING; HEADER REQUIRED; ALMOST JSON RESPONSE fxempire1, # XIGNITE BACKDOOR; HEADER REQUIRED; CLOUDFARE SPOOFING fxempire2, # TRADINGVIEW BACKDOOR fxrate, # XML SCRAPING ino, # DARKWEB API investing, # CLOUDFARE SPOOFING, XML SCRAPING liveusd, # DARKWEB API oanda, # DARKWEB API; RC4 ECRYPTION OF LATIN ENCODING reuters, # REFINITIV BACKDOOR, DARKWEB API wocu, # XML SCRAPING wsj, # MARKETWATCH BACKDOOR, DARKWEB API yahoo, # YAHOO FINANCE V7 DARKWEB API ] # initialize each external call method as a process processes = {} for method in methods: site = method.__name__ race_write(f"{site}_forex.txt", {}) processes[site] = Process(target=method, args=(site, )) processes[site].daemon = False processes[site].start() for site in processes.keys(): processes[site].join(TIMEOUT) for site in processes.keys(): processes[site].terminate() # read the text pipe ipc results of each process sources = {} for site in processes.keys(): sources[site] = race_read_json(f"{site}_forex.txt") return sources
def process_request(api): """ Multiprocessing Durability Wrapper for External Requests interprocess communication via durable text pipe """ begin = time.time() # multiprocessing completion signal signal = Value("i", 0) # several iterations of external requests until satisfied with response i = 0 while (i < ATTEMPTS) and not signal.value: # multiprocessing text file name nonce api["nonce"] = time.time() i += 1 if i > 1: print( "{} {} PUBLIC attempt:".format(api["exchange"], api["pair"]), i, time.ctime(), int(time.time()), ) child = Process(target=request, args=(api, signal)) child.daemon = False child.start() child.join(TIMEOUT) child.terminate() time.sleep(i**2) # the doc was created by the subprocess; read and destroy it doc = (api["exchange"] + api["pair"] + str(int(10**6 * api["nonce"])) + "_{}_public.txt".format(api["exchange"])) data = race_read_json(doc) path = PATH + "pipe/" if os.path.isfile(path + doc): os.remove(path + doc) if i > 1: print( "{} {} PUBLIC elapsed:".format(api["exchange"], api["pair"]), ("%.2f" % (time.time() - begin)), ) return data
def add_producer(name, wif): """ update authorized feed producers with broker(order) method """ edicts = [] nodes = race_read_json("nodes.txt") header = { "account_name": name, "wif": wif, } edict = { "op": "producer", "asset_id": ASSET_ID, "producer_ids": PRODUCER_IDS, } order = { "header": header, "edicts": [edict], "nodes": nodes, } broker(order)
def publish_feed(prices, name, wif): """ update the feed price on the blockchain using broker(order) method """ # gather the node list created by dex_process nodes = race_read_json("nodes.txt") # attach your account name and wif to the header header = { "account_name": name, "wif": wif, } pub_dict = { "op": "publish", "CER": CER, "MSSR": MSSR, "MCR": MCR, "currency_name": "BTS", } # create publication edict for each MPA # include standard publication dictionary parameters with unique name and price btscny = dict(pub_dict) btscny["asset_name"] = "HONEST.CNY" btscny["settlement_price"] = prices["feed"]["BTS:CNY"] btsusd = dict(pub_dict) btsusd["asset_name"] = "HONEST.USD" btsusd["settlement_price"] = prices["feed"]["BTS:USD"] btsbtc = dict(pub_dict) btsbtc["asset_name"] = "HONEST.BTC" btsbtc["settlement_price"] = prices["feed"]["BTS:BTC"] btsxag = dict(pub_dict) btsxag["asset_name"] = "HONEST.XAG" btsxag["settlement_price"] = prices["feed"]["BTS:XAG"] btsxau = dict(pub_dict) btsxau["asset_name"] = "HONEST.XAU" btsxau["settlement_price"] = prices["feed"]["BTS:XAU"] # btsltc = dict(pub_dict) # btsltc["asset_name"] = "HONEST.LTC" # btsltc["settlement_price"] = prices["feed"]["BTS:LTC"] btseth = dict(pub_dict) btseth["asset_name"] = "HONEST.ETH" btseth["settlement_price"] = prices["feed"]["BTS:ETH"] btsxrp = dict(pub_dict) btsxrp["asset_name"] = "HONEST.XRP" btsxrp["settlement_price"] = prices["feed"]["BTS:XRP"] btseth1 = dict(pub_dict) # these are a little different; we'll override currency name and add core price btseth1["asset_name"] = "HONEST.ETH1" btseth1["currency_name"] = "HONEST.BTC" btseth1["core_price"] = prices["feed"]["BTS:ETH"] btseth1["settlement_price"] = prices["feed"]["BTC:ETH"] btsxrp1 = dict(pub_dict) btsxrp1["asset_name"] = "HONEST.XRP1" btsxrp1["currency_name"] = "HONEST.BTC" btsxrp1["core_price"] = prices["feed"]["BTS:XRP"] btsxrp1["settlement_price"] = prices["feed"]["BTC:XRP"] # add each publication edict to the edicts list edicts = [btscny, btsusd, btsbtc, btsxag, btsxau, btseth, btsxrp, btseth1, btsxrp1] # construct and broker() the publication order dictionary order = { "header": header, "edicts": edicts, "nodes": nodes, } broker(order)
def gather_data(name, wif, trigger): """ primary event loop """ # purge the IPC text pipe race_write("pricefeed_final.txt", {}) race_write("pricefeed_forex.txt", {}) race_write("pricefeed_cex.txt", {}) race_write("pricefeed_dex.txt", {}) race_write("sceletus_output.txt", []) race_write("honest_cross_rates.txt", {}) race_write("feed.txt", {}) # begin the dex pricefeed (metanode fork) dex_process = Process(target=pricefeed_dex) dex_process.daemon = False dex_process.start() # dex_process.join(10) dex = {} # wait until the first dex pricefeed writes to file while dex == {}: dex = race_read_json("pricefeed_dex.txt") updates = 1 while True: try: # collect forex and cex data forex = pricefeed_forex() # takes about 30 seconds cex = pricefeed_cex() # takes about 30 seconds # read the latest dex data dex = race_read_json("pricefeed_dex.txt") # localize forex rates usdcny = forex["medians"]["USD:CNY"][0] # usdeur = forex["medians"]["USD:EUR"][0] # usdgbp = forex["medians"]["USD:GBP"][0] # usdrub = forex["medians"]["USD:RUB"][0] # usdjpy = forex["medians"]["USD:JPY"][0] # usdkrw = forex["medians"]["USD:KRW"][0] usdxau = forex["medians"]["USD:XAU"][0] usdxag = forex["medians"]["USD:XAG"][0] # localize cex rates btcusd = cex["BTC:USD"]["median"] cex_btsbtc = cex["BTS:BTC"]["median"] cex_btsbtc_list = [] for key, val in cex["BTS:BTC"]["data"].items(): cex_btsbtc_list.append(val["last"]) # attain dex BTS:BTC median dex_btsbtc_list = [v for k, v in dex["last"].items() if "BTC" in k] dex_btsbtc = median(dex_btsbtc_list) # finalize btsbtc by taking median of all cex and dex btsbtc prices btsbtc = median(dex_btsbtc_list + cex_btsbtc_list) # create feed prices for crypto altcoins: LTC, ETH, XRP # btcltc = 1/cex["LTC:BTC"]["median"] btceth = 1 / cex["ETH:BTC"]["median"] btcxrp = 1 / cex["XRP:BTC"]["median"] # btsltc = btsbtc * btcltc btseth = btsbtc * btceth btsxrp = btsbtc * btcxrp # create implied bts us dollar price btsusd = btsbtc * btcusd # create implied bts priced in forex terms feed = { "BTC:ETH": btceth, "BTC:XRP": btcxrp, "BTS:ETH": btseth, "BTS:XRP": btsxrp, "BTS:BTC": btsbtc, "BTS:USD": btsusd, "BTS:CNY": (btsusd * usdcny), # "BTS:EUR": (btsusd * usdeur), # "BTS:GBP": (btsusd * usdgbp), # "BTS:RUB": (btsusd * usdrub), # "BTS:JPY": (btsusd * usdjpy), # "BTS:KRW": (btsusd * usdkrw), "BTS:XAU": (btsusd * usdxau), "BTS:XAG": (btsusd * usdxag), } feed = {k: sigfig(v) for k, v in feed.items()} # forex priced in bts terms; switch symbol and 1/price inverse_feed = { (k[-3:] + ":" + k[:3]): sigfig(1 / v) for k, v in feed.items() } # aggregate full price calculation for jsonbin.io current_time = { "unix": int(time.time()), "local": time.ctime() + " " + time.strftime("%Z"), "utc": time.asctime(time.gmtime()) + " UTC", "runtime": int(time.time() - BEGIN), "updates": updates, } prices = { "time": current_time, "cex": cex, "dex": dex, "forex": forex, "inverse": inverse_feed, "feed": feed, } # update final output on disk race_write(doc="feed.txt", text=feed) race_write(doc="pricefeed_final.txt", text=json_dumps(prices)) # publish feed prices to the blockchain if trigger["feed"] == "y": time.sleep(3) print("\n", it("red", "PUBLISHING TO BLOCKCHAIN")) time.sleep(5) publish_feed(prices, name, wif) # upload production data matrix to jsonbin.io if trigger["jsonbin"] == "y": time.sleep(3) print("\n", it("red", "UPLOADING TO JSONBIN")) time.sleep(5) update_jsonbin(prices) # buy/sell reference rates with two accounts msg = "DEMO SCELETUS REFERENCE RATES" if trigger["sceletus"] == "y": if trigger["cancel"] == "y": time.sleep(3) print("\n", it("red", "CANCEL ALL IN ALL MARKETS")) time.sleep(5) cancel_all_markets(name, wif) msg = msg.replace("DEMO ", "") time.sleep(3) print("\n", it("red", msg)) time.sleep(5) sceletus_orders, sceletus_output = sceletus( prices, name, wif, trigger["sceletus"] ) race_append("sceletus_orders.txt", ("\n\n" + json_dumps(sceletus_orders))) race_write("sceletus_output.txt", json_dumps(sceletus_output)) appendage = ( "\n" + str(int(time.time())) + " " + time.ctime() + " " + str(feed) ) race_append(doc="feed_append.txt", text=appendage) updates += 1 time.sleep(REFRESH) except Exception as error: print(error) time.sleep(10) # try again in 10 seconds
def sceletus(prices, name, wif, do_sceletus): """ update the historic chart on the blockchain using buy/sell broker(order) method for each pair to be skeleton'd, for each agent on opposing sides of the book """ orders = [] order_dict = {} header = {} tick = prices["time"]["updates"] # create a list of all pairs to be skeleton'd pairs = create_pairs(tick) # websocket handshake rpc = reconnect(None) # remote procedure price of bts to Bitassets rates bitassets = fetch_bts_bitassets(rpc) account_id = "" if do_sceletus: account_id = rpc_lookup_accounts(rpc, {"account_name": name}) # build qty_rate dict qty_rate = create_qty_rate(prices, bitassets) # each agent will place a limit order for each market pair for pair in pairs: amount = sigfig(qty_rate[pair]["qty"]) price = sigfig(qty_rate[pair]["rate"]) order_dict[pair] = [amount, price] # sort pair into dict of asset and currency asset = pair.split(":")[0] currency = pair.split(":")[1] pair_dict = { "asset": asset, "currency": currency, } # flash the curreny pair being bought/sold msg = "\033c\n\n\n" msg += it("red", "SCELETUS") msg += "\n\n\n" for i in range(50): msg += ("\n " + asset + " : " + currency + " @ " + it("cyan", price) + " qty " + it("yellow", amount)) print(msg) # make rpc for A.B.C id's and precisions ( asset_id, asset_precision, currency_id, currency_precision, ) = rpc_lookup_asset_symbols(rpc, pair_dict) # update the header respectively header["asset_id"] = asset_id header["currency_id"] = currency_id header["asset_precision"] = asset_precision header["currency_precision"] = currency_precision # perform buy ops for agents[0] and sell ops for agents[1] for idx in range(2): # build the header with correct account info header["account_name"] = name header["account_id"] = account_id header["wif"] = wif operation = ["buy", "sell"][idx] # build the final edict for this agent*pair with operation and qty_rate edict = { "op": operation, "amount": amount, "price": price, "expiration": 0, } # fetch the nodes list and shuffle nodes = race_read_json("nodes.txt") random.shuffle(nodes) # build the order with agent appropriate header and edict for this pair order = { "header": header, "edicts": [edict], "nodes": nodes, } # print the outcome and if not a demo, then live execution orders.append({ "time": time.ctime(), "unix": int(time.time()), "tick": tick, "name": name, "op": operation, "pair": pair, "price": price, "amount": amount, }) if do_sceletus: broker(order) return orders, order_dict
def sceletus(prices, gateway, name, wif, do_sceletus): """ update the historic chart on the blockchain using buy/sell broker(order) method for each pair to be skeleton'd, for each agent on opposing sides of the book """ orders = [] order_dict = {} header = {} # build qty_rate dict qty_rate = create_qty_rate(prices, gateway) print("\033c") print_logo() print("\n\nQTY_RATE") for k, v in qty_rate.items(): print(k, v, it("cyan", sigfig(1 / v["rate"]))) time.sleep(5) print(it("green", "Begin sceletus buy/sell ops...")) time.sleep(5) account_id = "" if do_sceletus: rpc = reconnect(None) account_id = rpc_lookup_accounts(rpc, {"account_name": name}) for pair in qty_rate.keys(): amount = sigfig(qty_rate[pair]["qty"]) price = sigfig(qty_rate[pair]["rate"]) order_dict[pair] = [amount, price] # sort pair into dict of asset and currency asset = pair.split(":")[0] currency = pair.split(":")[1] pair_dict = { "asset": asset, "currency": currency, } # flash the curreny pair being bought/sold msg = "\033c\n\n\n" msg += it("red", "SCELETUS") msg += "\n\n\n" for _ in range(50): msg += ("\n " + asset + " : " + currency + " @ " + it("cyan", price) + " qty " + it("yellow", amount)) print(msg) # make rpc for A.B.C id's and precisions ( asset_id, asset_precision, currency_id, currency_precision, ) = rpc_lookup_asset_symbols(rpc, pair_dict) # update the header respectively header["asset_id"] = asset_id header["currency_id"] = currency_id header["asset_precision"] = asset_precision header["currency_precision"] = currency_precision # perform buy ops for agents[0] and sell ops for agents[1] for idx in range(2): # build the header with correct account info header["account_name"] = name header["account_id"] = account_id header["wif"] = wif operation = ["buy", "sell"][idx] # build the final edict for this agent*pair with operation and qty_rate edict = { "op": operation, "amount": amount, "price": price, "expiration": 0, } # fetch the nodes list and shuffle nodes = race_read_json("nodes.txt") shuffle(nodes) # build the order with agent appropriate header and edict for this pair order = { "header": header, "edicts": [edict], "nodes": nodes, } # print the outcome and if not a demo, then live execution orders.append({ "time": time.ctime(), "unix": int(time.time()), "name": name, "op": operation, "pair": pair, "price": price, "amount": amount, }) if do_sceletus: broker(order) if do_sceletus: print("\033c") print_logo() print(it("cyan", "OPEN ORDERS")) rpc_open_orders(rpc, name) return orders, order_dict