def update_price_feed() : global derived_prices, config state = {} for asset in _all_assets + [core_symbol]: price_median_blockchain[asset] = 0.0 lastUpdate[asset] = datetime.utcnow() myCurrentFeed[asset] = {} if configFile.blame != "latest" : blameFile = config.configPath + "/blame/" + configFile.blame + ".json" if os.path.isfile(blameFile) : # Load data from disk for (faster) debugging and verification with open(blameFile, 'r') as fp: state = json.load(fp) # Load feed sources feed = state["feed"] # Load configuration from old state configStruct = state["config"] for key in configStruct : # Skip asset config if key == "asset_config" : continue config.__dict__[key] = configStruct[key] else : sys.exit("Configuration error: Either set 'blame' to an existing " + "block number from the blame/ to verify or set it to " + "'latest' to run the script online! ") else : # Load configuration from file config = configFile # Get prices online from sources pool = futures.ThreadPoolExecutor(max_workers=8) feed = {} mythreads = {} for name in config.feedSources : print("(%s)" % name, end="", flush=True) mythreads[name] = pool.submit(config.feedSources[name].fetch) for name in config.feedSources : print(".", end="", flush=True) feed[name] = mythreads[name].result() # rpc variables about bts rpc ############################################## rpc = GrapheneAPI(config.host, config.port, config.user, config.passwd) fetch_from_wallet(rpc) # Determine bts price ###################################################### derived_prices = derive_prices(feed) # Only publish given feeds ################################################# price_feeds = {} update_required = False for asset in asset_list_publish : # Get Final Price according to price metric this_asset_config = config.asset_config[asset] if asset in config.asset_config else config.asset_config["default"] price_metric = this_asset_config["metric"] if "metric" in this_asset_config else config.asset_config["default"]["metric"] if (asset not in derived_prices or core_symbol not in derived_prices[asset] or price_metric not in derived_prices[asset][core_symbol]) : print("Warning: Asset %s has no derived price!" % asset) continue if float(derived_prices[asset][core_symbol][price_metric]) > 0.0: quote_precision_core = assets[asset]["precision"] symbol = assets[asset]["symbol"] assert symbol is not asset base_precision_cer = assets[blockchain_feed_quote[asset]]["precision"] # core asset core_price_cer = derived_prices[asset][core_symbol][price_metric] * 10 ** (quote_precision_core - base_precision_cer) core_price_cer = fractions.Fraction.from_float(core_price_cer).limit_denominator(100000) denominator_cer = core_price_cer.denominator numerator_cer = core_price_cer.numerator quote_precision_settle = assets[asset]["precision"] symbol = assets[asset]["symbol"] assert symbol is not asset base_precision_settle = assets[blockchain_feed_quote[asset]]["precision"] # core asset core_price_settle = derived_prices[asset]["short_backing_asset"][price_metric] * 10 ** (quote_precision_settle - base_precision_settle) core_price_settle = fractions.Fraction.from_float(core_price_settle).limit_denominator(100000) denominator_settle = core_price_settle.denominator numerator_settle = core_price_settle.numerator price_feed = {"settlement_price": { "quote": {"asset_id": assets[blockchain_feed_quote[asset]]["id"], "amount": denominator_settle }, "base": {"asset_id": assets[asset]["id"], "amount": numerator_settle } }, "maintenance_collateral_ratio" : config.asset_config[symbol]["maintenance_collateral_ratio"] if (symbol in config.asset_config and "maintenance_collateral_ratio" in config.asset_config[symbol]) else config.asset_config["default"]["maintenance_collateral_ratio"], "maximum_short_squeeze_ratio" : config.asset_config[symbol]["maximum_short_squeeze_ratio"] if (symbol in config.asset_config and "maximum_short_squeeze_ratio" in config.asset_config[symbol]) else config.asset_config["default"]["maximum_short_squeeze_ratio"], "core_exchange_rate": { "quote": {"asset_id": "1.3.0", "amount": int(denominator_cer * ( config.asset_config[symbol]["core_exchange_factor"] if (symbol in config.asset_config and "core_exchange_factor" in config.asset_config[symbol]) else config.asset_config["default"]["core_exchange_factor"])) }, "base": {"asset_id": assets[asset]["id"], "amount": numerator_cer }}} asset_update_required = publish_rule(rpc, asset) if asset_update_required : update_required = True price_feeds[symbol] = {"asset_id": assets[asset]["id"], "feed": price_feed, "publish": asset_update_required } else : print("Warning: Asset %s has a negative derived price of %f (%s metric)!" % (asset, float(derived_prices[asset][price_metric]), price_metric)) continue if not debug : # Print some stats ########################################################## print_stats(price_feeds) # Verify results or store them ############################################## configStruct = {} for key in dir(config) : if key[0] == "_" : continue if key == "feedSources" : continue if key == "feedsources" : continue if key == "subprocess" : continue if key == "os" : continue configStruct[key] = config.__dict__[key] # Store State state["feed"] = feed state["derived_prices"] = derived_prices state["price_feeds"] = price_feeds state["lastblock"] = get_last_block(rpc) state["config"] = configStruct blameFile = config.configPath + "/blame/" + str(state["lastblock"]) + ".json" with open(blameFile, 'w') as fp: json.dump(state, fp) print("Blamefile: " + blameFile) # Check publish rules and publich feeds ##################################### if update_required and not debug : publish = False if config.ask_confirmation : if rpc._confirm("Are you SURE you would like to publish this feed?") : publish = True else : publish = True if publish : print("Update required! Forcing now!") update_feed(rpc, price_feeds) else : print("no update required") else : # Verify results print() print("[Warning] This script is loading old data for debugging. No price can be published.\n" + " Please set 'blame' to 'latest' if you are ready to go online!") print() compare_feeds(state["derived_prices"], derived_prices)
def update_price_feed(): global derived_prices, config state = {} for asset in _all_assets + [core_symbol]: price_median_blockchain[asset] = 0.0 lastUpdate[asset] = datetime.utcnow() myCurrentFeed[asset] = {} if configFile.blame != "latest": blameFile = config.configPath + "/blame/" + configFile.blame + ".json" if os.path.isfile(blameFile): # Load data from disk for (faster) debugging and verification with open(blameFile, 'r') as fp: state = json.load(fp) # Load feed sources feed = state["feed"] # Load configuration from old state configStruct = state["config"] for key in configStruct: # Skip asset config if key == "asset_config": continue config.__dict__[key] = configStruct[key] else: sys.exit( "Configuration error: Either set 'blame' to an existing " + "block number from the blame/ to verify or set it to " + "'latest' to run the script online! ") else: # Load configuration from file config = configFile # Get prices online from sources pool = futures.ThreadPoolExecutor(max_workers=8) feed = {} mythreads = {} for name in config.feedSources: print("(%s)" % name, end="", flush=True) mythreads[name] = pool.submit(config.feedSources[name].fetch) for name in config.feedSources: print(".", end="", flush=True) feed[name] = mythreads[name].result() # rpc variables about bts rpc ############################################## rpc = GrapheneAPI(config.host, config.port, config.user, config.passwd) fetch_from_wallet(rpc) # Determine bts price ###################################################### derived_prices = derive_prices(feed) # Only publish given feeds ################################################# price_feeds = {} update_required = False for asset in asset_list_publish: # Get Final Price according to price metric this_asset_config = config.asset_config[ asset] if asset in config.asset_config else config.asset_config[ "default"] price_metric = this_asset_config[ "metric"] if "metric" in this_asset_config else config.asset_config[ "default"]["metric"] if (asset not in derived_prices or core_symbol not in derived_prices[asset] or price_metric not in derived_prices[asset][core_symbol]): print("Warning: Asset %s has no derived price!" % asset) continue if float(derived_prices[asset][core_symbol][price_metric]) > 0.0: quote_precision_core = assets[asset]["precision"] symbol = assets[asset]["symbol"] assert symbol is not asset base_precision_cer = assets[blockchain_feed_quote[asset]][ "precision"] # core asset core_price_cer = derived_prices[asset][core_symbol][ price_metric] * 10**(quote_precision_core - base_precision_cer) core_price_cer = fractions.Fraction.from_float( core_price_cer).limit_denominator(100000) denominator_cer = core_price_cer.denominator numerator_cer = core_price_cer.numerator quote_precision_settle = assets[asset]["precision"] symbol = assets[asset]["symbol"] assert symbol is not asset base_precision_settle = assets[blockchain_feed_quote[asset]][ "precision"] # core asset core_price_settle = derived_prices[asset]["short_backing_asset"][ price_metric] * 10**(quote_precision_settle - base_precision_settle) core_price_settle = fractions.Fraction.from_float( core_price_settle).limit_denominator(100000) denominator_settle = core_price_settle.denominator numerator_settle = core_price_settle.numerator price_feed = { "settlement_price": { "quote": { "asset_id": assets[blockchain_feed_quote[asset]]["id"], "amount": denominator_settle }, "base": { "asset_id": assets[asset]["id"], "amount": numerator_settle } }, "maintenance_collateral_ratio": config.asset_config[symbol]["maintenance_collateral_ratio"] if (symbol in config.asset_config and "maintenance_collateral_ratio" in config.asset_config[symbol]) else config.asset_config["default"]["maintenance_collateral_ratio"], "maximum_short_squeeze_ratio": config.asset_config[symbol]["maximum_short_squeeze_ratio"] if (symbol in config.asset_config and "maximum_short_squeeze_ratio" in config.asset_config[symbol]) else config.asset_config["default"]["maximum_short_squeeze_ratio"], "core_exchange_rate": { "quote": { "asset_id": "1.3.0", "amount": int(denominator_cer * (config.asset_config[symbol] ["core_exchange_factor"] if (symbol in config.asset_config and "core_exchange_factor" in config.asset_config[symbol]) else config. asset_config["default"]["core_exchange_factor"])) }, "base": { "asset_id": assets[asset]["id"], "amount": numerator_cer } } } asset_update_required = publish_rule(rpc, asset) if asset_update_required: update_required = True price_feeds[symbol] = { "asset_id": assets[asset]["id"], "feed": price_feed, "publish": asset_update_required } else: print( "Warning: Asset %s has a negative derived price of %f (%s metric)!" % (asset, float( derived_prices[asset][price_metric]), price_metric)) continue if not debug: # Print some stats ########################################################## print_stats(price_feeds) # Verify results or store them ############################################## configStruct = {} for key in dir(config): if key[0] == "_": continue if key == "feedSources": continue if key == "feedsources": continue if key == "subprocess": continue if key == "os": continue configStruct[key] = config.__dict__[key] # Store State state["feed"] = feed state["derived_prices"] = derived_prices state["price_feeds"] = price_feeds state["lastblock"] = get_last_block(rpc) state["config"] = configStruct blameFile = config.configPath + "/blame/" + str( state["lastblock"]) + ".json" with open(blameFile, 'w') as fp: json.dump(state, fp) print("Blamefile: " + blameFile) # Check publish rules and publich feeds ##################################### if update_required and not debug: publish = False if config.ask_confirmation: if rpc._confirm( "Are you SURE you would like to publish this feed?"): publish = True else: publish = True if publish: print("Update required! Forcing now!") update_feed(rpc, price_feeds) else: print("no update required") else: # Verify results print() print( "[Warning] This script is loading old data for debugging. No price can be published.\n" + " Please set 'blame' to 'latest' if you are ready to go online!" ) print() compare_feeds(state["derived_prices"], derived_prices)