|
|
@@ -12,16 +12,13 @@ import plotly.graph_objects as go
|
|
|
from plotly.utils import PlotlyJSONEncoder
|
|
|
|
|
|
# --- 配置部分 ---
|
|
|
-# OpenOcean (假设 'SOL' 是输入, 'RFC' 是输出, 得到 RFC/SOL 价格)
|
|
|
IN_TOKEN_ADDRESS_SOLANA = 'So11111111111111111111111111111111111111112' # SOL Mint Address
|
|
|
-OUT_TOKEN_ADDRESS_SOLANA = 'DitHyRMQiSDhn5cnKMJV2CDDt6sVct96YrECiM49pump' # RFC Mint Address (示例)
|
|
|
-AMOUNT_TO_QUERY_OPENOCEAN_IN_SOL = decimal.Decimal('10') # 例如用 10 SOL 去查询能买多少 RFC
|
|
|
+OUT_TOKEN_ADDRESS_SOLANA = '38PgzpJYu2HkiYvV8qePFakB8tuobPdGm2FFEn7Dpump' #OutToken
|
|
|
+AMOUNT_TO_QUERY_OPENOCEAN_IN_SOL = decimal.Decimal('10')
|
|
|
|
|
|
-# Gate.io (RFC/USDT)
|
|
|
-GATEIO_SPOT_PAIR_RFC_USDT = 'HOUSE_USDT'
|
|
|
-GATEIO_FUTURES_CONTRACT_RFC_USDT = 'HOUSE_USDT'
|
|
|
+GATEIO_SPOT_PAIR_RFC_USDT = 'GORK_USDT'
|
|
|
+# GATEIO_FUTURES_CONTRACT_RFC_USDT = 'GORK_USDT' # 注释掉期货配置
|
|
|
|
|
|
-# Binance (SOL/USDT - 用于转换)
|
|
|
BINANCE_SOL_USDT_PAIR = 'SOLUSDT'
|
|
|
|
|
|
proxies = None
|
|
|
@@ -29,7 +26,7 @@ decimal.getcontext().prec = 36
|
|
|
|
|
|
|
|
|
# --- 价格获取函数 ---
|
|
|
-def get_openocean_price_solana(in_token_addr, out_token_addr, human_amount_in_decimal_for_request): # Solana gas is low
|
|
|
+def get_openocean_price_solana(in_token_addr, out_token_addr, human_amount_in_decimal_for_request):
|
|
|
chain = 'solana'
|
|
|
url = f'https://open-api.openocean.finance/v4/{chain}/quote'
|
|
|
params = {'inTokenAddress': in_token_addr, 'outTokenAddress': out_token_addr,
|
|
|
@@ -45,12 +42,11 @@ def get_openocean_price_solana(in_token_addr, out_token_addr, human_amount_in_de
|
|
|
'decimals') is None: return {"error": "OO API缺少数据"}
|
|
|
in_dec, out_dec = int(d['inToken']['decimals']), int(d['outToken']['decimals'])
|
|
|
atomic_in, atomic_out = decimal.Decimal(d['inAmount']), decimal.Decimal(d['outAmount'])
|
|
|
- h_in_sol = atomic_in / (10 ** in_dec) # 这是花费的SOL数量
|
|
|
- h_out_rfc = atomic_out / (10 ** out_dec) # 这是得到的RFC数量
|
|
|
+ h_in_sol = atomic_in / (10 ** in_dec);
|
|
|
+ h_out_rfc = atomic_out / (10 ** out_dec)
|
|
|
if h_out_rfc == 0: return {"error": "OO输出RFC为0"}
|
|
|
- # 价格:1 RFC = X SOL => SOL数量 / RFC数量
|
|
|
price_rfc_per_sol = h_in_sol / h_out_rfc
|
|
|
- return {"price_sol_per_rfc": price_rfc_per_sol} # 更明确的键名
|
|
|
+ return {"price_sol_per_rfc": price_rfc_per_sol}
|
|
|
else:
|
|
|
return {
|
|
|
"error": f"OO API错误 - Code:{data.get('code', 'N/A')}, Msg:{data.get('msg', data.get('message', 'N/A')) if isinstance(data, dict) else '格式错误'}"}
|
|
|
@@ -58,7 +54,7 @@ def get_openocean_price_solana(in_token_addr, out_token_addr, human_amount_in_de
|
|
|
return {"error": f"OO(Solana)请求错误: {e}"}
|
|
|
|
|
|
|
|
|
-def get_gateio_spot_price_usdt(pair_symbol): # 获取 RFC/USDT
|
|
|
+def get_gateio_spot_price_usdt(pair_symbol):
|
|
|
url = f'https://api.gateio.ws/api/v4/spot/tickers';
|
|
|
params = {'currency_pair': pair_symbol}
|
|
|
try:
|
|
|
@@ -67,7 +63,7 @@ def get_gateio_spot_price_usdt(pair_symbol): # 获取 RFC/USDT
|
|
|
data = r.json()
|
|
|
if isinstance(data, list) and data:
|
|
|
td = data[0]
|
|
|
- if td.get('currency_pair') == pair_symbol and td.get('lowest_ask'):
|
|
|
+ if td.get('currency_pair') == pair_symbol and td.get('lowest_ask'): # 使用 lowest_ask 作为卖价
|
|
|
return {"price_rfc_usdt": decimal.Decimal(td['lowest_ask'])}
|
|
|
else:
|
|
|
return {"error": f"Gate现货({pair_symbol})数据不匹配或无价格"}
|
|
|
@@ -79,41 +75,30 @@ def get_gateio_spot_price_usdt(pair_symbol): # 获取 RFC/USDT
|
|
|
return {"error": f"Gate现货({pair_symbol})请求错误: {e}"}
|
|
|
|
|
|
|
|
|
-def get_gateio_futures_price_usdt(contract_symbol, settle_currency='usdt'): # 获取 RFC/USDT
|
|
|
- url = f'https://api.gateio.ws/api/v4/futures/{settle_currency}/tickers';
|
|
|
- params = {'contract': contract_symbol}
|
|
|
+# def get_gateio_futures_price_usdt(contract_symbol, settle_currency='usdt'): # 注释掉期货函数
|
|
|
+# url = f'https://api.gateio.ws/api/v4/futures/{settle_currency}/tickers'; params = {'contract': contract_symbol}
|
|
|
+# try:
|
|
|
+# r = requests.get(url, params=params, proxies=proxies, timeout=10); r.raise_for_status(); data = r.json()
|
|
|
+# if isinstance(data, list) and data:
|
|
|
+# td = data[0]
|
|
|
+# if td.get('contract') == contract_symbol and td.get('highest_bid'): # 使用 highest_bid 作为买价
|
|
|
+# return {"price_rfc_usdt": decimal.Decimal(td['highest_bid'])}
|
|
|
+# else: return {"error": f"Gate期货({contract_symbol})数据不匹配或无价格"}
|
|
|
+# elif isinstance(data, dict) and data.get('label'): return {"error": f"Gate期货API错误: {data['label']}-{data.get('message','')}"}
|
|
|
+# else: return {"error": f"Gate期货API({contract_symbol})数据格式错误或未找到"}
|
|
|
+# except Exception as e: return {"error": f"Gate期货({contract_symbol})请求错误: {e}"}
|
|
|
+
|
|
|
+def get_binance_spot_price_usdt(symbol):
|
|
|
+ url = "https://api.binance.com/api/v3/ticker/price";
|
|
|
+ params = {'symbol': symbol}
|
|
|
try:
|
|
|
- r = requests.get(url, params=params, proxies=proxies, timeout=10);
|
|
|
- r.raise_for_status();
|
|
|
- data = r.json()
|
|
|
- if isinstance(data, list) and data:
|
|
|
- td = data[0]
|
|
|
- if td.get('contract') == contract_symbol and td.get('highest_bid'):
|
|
|
-
|
|
|
- return {"price_rfc_usdt": decimal.Decimal(td['highest_bid'])}
|
|
|
- else:
|
|
|
- return {"error": f"Gate期货({contract_symbol})数据不匹配或无价格"}
|
|
|
- elif isinstance(data, dict) and data.get('label'):
|
|
|
- return {"error": f"Gate期货API错误: {data['label']}-{data.get('message', '')}"}
|
|
|
- else:
|
|
|
- return {"error": f"Gate期货API({contract_symbol})数据格式错误或未找到"}
|
|
|
- except Exception as e:
|
|
|
- return {"error": f"Gate期货({contract_symbol})请求错误: {e}"}
|
|
|
-
|
|
|
-
|
|
|
-def get_binance_spot_price_usdt(symbol): # 获取 SOL/USDT
|
|
|
- # 使用币安现货API: https://binance-docs.github.io/apidocs/spot/en/#ticker-price
|
|
|
- url = "https://api.binance.com/api/v3/ticker/price"
|
|
|
- params = {'symbol': symbol} # e.g., 'SOLUSDT'
|
|
|
- try:
|
|
|
- response = requests.get(url, params=params, proxies=proxies, timeout=10)
|
|
|
- response.raise_for_status()
|
|
|
+ response = requests.get(url, params=params, proxies=proxies, timeout=10);
|
|
|
+ response.raise_for_status();
|
|
|
data = response.json()
|
|
|
if 'price' in data and data.get('symbol') == symbol:
|
|
|
return {"price_sol_usdt": decimal.Decimal(data['price'])}
|
|
|
else:
|
|
|
- msg = data.get('msg', '未知错误')
|
|
|
- return {"error": f"Binance API错误 ({symbol}): {msg}"}
|
|
|
+ msg = data.get('msg', '未知错误'); return {"error": f"Binance API错误 ({symbol}): {msg}"}
|
|
|
except requests.exceptions.RequestException as e:
|
|
|
return {"error": f"Binance API ({symbol}) 请求失败: {e}"}
|
|
|
except Exception as e:
|
|
|
@@ -124,36 +109,37 @@ app = Flask(__name__)
|
|
|
log = logging.getLogger('werkzeug');
|
|
|
log.setLevel(logging.ERROR)
|
|
|
|
|
|
-MAX_HISTORY_POINTS_PLOTLY = 86400
|
|
|
+MAX_HISTORY_POINTS_PLOTLY = 86400 # 你坚持要这个值,保留它,但请注意性能
|
|
|
REFRESH_INTERVAL_SECONDS = 1
|
|
|
|
|
|
historical_data_points = deque(maxlen=MAX_HISTORY_POINTS_PLOTLY)
|
|
|
latest_values_for_table = {
|
|
|
- "oo_rfc_sol_price": "N/A", # OpenOcean RFC/SOL
|
|
|
- "gate_spot_rfc_sol_price": "N/A", # Gate Spot RFC/USDT converted to RFC/SOL
|
|
|
- "gate_futures_rfc_sol_price": "N/A", # Gate Futures RFC/USDT converted to RFC/SOL
|
|
|
- "sol_usdt_price_binance": "N/A", # For reference
|
|
|
+ "oo_rfc_sol_price": "N/A",
|
|
|
+ "gate_spot_rfc_sol_price": "N/A",
|
|
|
+ # "gate_futures_rfc_sol_price": "N/A", # 注释
|
|
|
+ "sol_usdt_price_binance": "N/A",
|
|
|
"diff_oo_vs_spot_rfc_sol_percentage": "N/A",
|
|
|
- "diff_oo_vs_futures_rfc_sol_percentage": "N/A",
|
|
|
- "diff_spot_vs_futures_rfc_sol_percentage": "N/A",
|
|
|
- "oo_error": None, "gate_spot_error": None, "gate_futures_error": None, "binance_sol_error": None,
|
|
|
+ # "diff_oo_vs_futures_rfc_sol_percentage": "N/A", # 注释
|
|
|
+ # "diff_spot_vs_futures_rfc_sol_percentage": "N/A", # 注释
|
|
|
+ "oo_error": None, "gate_spot_error": None,
|
|
|
+ # "gate_futures_error": None, # 注释
|
|
|
+ "binance_sol_error": None,
|
|
|
"last_updated": "N/A",
|
|
|
"gate_spot_pair_name_usdt": GATEIO_SPOT_PAIR_RFC_USDT,
|
|
|
- "gate_futures_contract_name_usdt": GATEIO_FUTURES_CONTRACT_RFC_USDT,
|
|
|
- "target_asset_symbol": GATEIO_SPOT_PAIR_RFC_USDT.split('_')[0] # RFC
|
|
|
+ # "gate_futures_contract_name_usdt": GATEIO_FUTURES_CONTRACT_RFC_USDT, # 注释
|
|
|
+ "target_asset_symbol": GATEIO_SPOT_PAIR_RFC_USDT.split('_')[0]
|
|
|
}
|
|
|
data_lock = threading.Lock()
|
|
|
|
|
|
|
|
|
def calculate_percentage_diff(price_a, price_b):
|
|
|
if price_a is not None and price_b is not None and isinstance(price_a, decimal.Decimal) and isinstance(price_b,
|
|
|
- decimal.Decimal) and price_b != 0: # 基准不能为0
|
|
|
+ decimal.Decimal) and price_b != 0:
|
|
|
return ((price_a - price_b) / price_b) * 100
|
|
|
return None
|
|
|
|
|
|
|
|
|
def convert_usdt_price_to_sol_price(price_asset_usdt, price_sol_usdt):
|
|
|
- """Converts Price(Asset/USDT) to Price(Asset/SOL) using Price(SOL/USDT)"""
|
|
|
if price_asset_usdt is not None and price_sol_usdt is not None and price_sol_usdt > 0:
|
|
|
return price_asset_usdt / price_sol_usdt
|
|
|
return None
|
|
|
@@ -161,7 +147,7 @@ def convert_usdt_price_to_sol_price(price_asset_usdt, price_sol_usdt):
|
|
|
|
|
|
def update_data_for_plotly_and_table():
|
|
|
global historical_data_points, latest_values_for_table
|
|
|
- print("数据更新线程启动...")
|
|
|
+ print("数据更新线程启动 (仅现货)...")
|
|
|
while True:
|
|
|
fetch_time_full = time.strftime("%Y-%m-%d %H:%M:%S")
|
|
|
fetch_time_chart = time.strftime("%H:%M:%S")
|
|
|
@@ -169,36 +155,34 @@ def update_data_for_plotly_and_table():
|
|
|
oo_data = get_openocean_price_solana(IN_TOKEN_ADDRESS_SOLANA, OUT_TOKEN_ADDRESS_SOLANA,
|
|
|
AMOUNT_TO_QUERY_OPENOCEAN_IN_SOL)
|
|
|
spot_usdt_data = get_gateio_spot_price_usdt(GATEIO_SPOT_PAIR_RFC_USDT)
|
|
|
- futures_usdt_data = get_gateio_futures_price_usdt(GATEIO_FUTURES_CONTRACT_RFC_USDT)
|
|
|
+ # futures_usdt_data = get_gateio_futures_price_usdt(GATEIO_FUTURES_CONTRACT_RFC_USDT) # 注释
|
|
|
binance_sol_usdt_data = get_binance_spot_price_usdt(BINANCE_SOL_USDT_PAIR)
|
|
|
|
|
|
- oo_rfc_sol_price = oo_data.get("price_sol_per_rfc") # 1 RFC = X SOL
|
|
|
- spot_rfc_usdt_price = spot_usdt_data.get("price_rfc_usdt") # 1 RFC = X USDT
|
|
|
- futures_rfc_usdt_price = futures_usdt_data.get("price_rfc_usdt") # 1 RFC = X USDT
|
|
|
- sol_usdt_price = binance_sol_usdt_data.get("price_sol_usdt") # 1 SOL = X USDT
|
|
|
+ oo_rfc_sol_price = oo_data.get("price_sol_per_rfc")
|
|
|
+ spot_rfc_usdt_price = spot_usdt_data.get("price_rfc_usdt")
|
|
|
+ # futures_rfc_usdt_price = futures_usdt_data.get("price_rfc_usdt") # 注释
|
|
|
+ sol_usdt_price = binance_sol_usdt_data.get("price_sol_usdt")
|
|
|
|
|
|
oo_err = oo_data.get("error")
|
|
|
spot_err = spot_usdt_data.get("error")
|
|
|
- futures_err = futures_usdt_data.get("error")
|
|
|
+ # futures_err = futures_usdt_data.get("error") # 注释
|
|
|
binance_err = binance_sol_usdt_data.get("error")
|
|
|
|
|
|
- # Convert Gate.io prices to RFC/SOL
|
|
|
spot_rfc_sol_price = convert_usdt_price_to_sol_price(spot_rfc_usdt_price, sol_usdt_price)
|
|
|
- futures_rfc_sol_price = convert_usdt_price_to_sol_price(futures_rfc_usdt_price, sol_usdt_price)
|
|
|
+ # futures_rfc_sol_price = convert_usdt_price_to_sol_price(futures_rfc_usdt_price, sol_usdt_price) # 注释
|
|
|
|
|
|
- # Calculate diffs based on RFC/SOL prices
|
|
|
diff_oo_spot_pct = calculate_percentage_diff(oo_rfc_sol_price, spot_rfc_sol_price)
|
|
|
- diff_oo_futures_pct = calculate_percentage_diff(oo_rfc_sol_price, futures_rfc_sol_price)
|
|
|
- diff_spot_futures_pct = calculate_percentage_diff(spot_rfc_sol_price, futures_rfc_sol_price)
|
|
|
+ # diff_oo_futures_pct = calculate_percentage_diff(oo_rfc_sol_price, futures_rfc_sol_price) # 注释
|
|
|
+ # diff_spot_futures_pct = calculate_percentage_diff(spot_rfc_sol_price, futures_rfc_sol_price) # 注释
|
|
|
|
|
|
current_point = {
|
|
|
"time": fetch_time_chart,
|
|
|
"oo_rfc_sol": float(oo_rfc_sol_price) if oo_rfc_sol_price else None,
|
|
|
"spot_rfc_sol": float(spot_rfc_sol_price) if spot_rfc_sol_price else None,
|
|
|
- "futures_rfc_sol": float(futures_rfc_sol_price) if futures_rfc_sol_price else None,
|
|
|
+ # "futures_rfc_sol": float(futures_rfc_sol_price) if futures_rfc_sol_price else None, # 注释
|
|
|
"diff_oo_spot_rfc_sol": float(diff_oo_spot_pct) if diff_oo_spot_pct is not None else None,
|
|
|
- "diff_oo_futures_rfc_sol": float(diff_oo_futures_pct) if diff_oo_futures_pct is not None else None,
|
|
|
- "diff_spot_futures_rfc_sol": float(diff_spot_futures_pct) if diff_spot_futures_pct is not None else None,
|
|
|
+ # "diff_oo_futures_rfc_sol": float(diff_oo_futures_pct) if diff_oo_futures_pct is not None else None, # 注释
|
|
|
+ # "diff_spot_futures_rfc_sol": float(diff_spot_futures_pct) if diff_spot_futures_pct is not None else None, # 注释
|
|
|
}
|
|
|
|
|
|
with data_lock:
|
|
|
@@ -207,36 +191,31 @@ def update_data_for_plotly_and_table():
|
|
|
latest_values_for_table["oo_rfc_sol_price"] = str(oo_rfc_sol_price) if oo_rfc_sol_price else "N/A"
|
|
|
latest_values_for_table["gate_spot_rfc_sol_price"] = str(
|
|
|
spot_rfc_sol_price) if spot_rfc_sol_price else "N/A"
|
|
|
- latest_values_for_table["gate_futures_rfc_sol_price"] = str(
|
|
|
- futures_rfc_sol_price) if futures_rfc_sol_price else "N/A"
|
|
|
+ # latest_values_for_table["gate_futures_rfc_sol_price"] = str(futures_rfc_sol_price) if futures_rfc_sol_price else "N/A" # 注释
|
|
|
latest_values_for_table["sol_usdt_price_binance"] = str(sol_usdt_price) if sol_usdt_price else "N/A"
|
|
|
|
|
|
latest_values_for_table[
|
|
|
"diff_oo_vs_spot_rfc_sol_percentage"] = f"{diff_oo_spot_pct:+.4f}%" if diff_oo_spot_pct is not None else "N/A"
|
|
|
- latest_values_for_table[
|
|
|
- "diff_oo_vs_futures_rfc_sol_percentage"] = f"{diff_oo_futures_pct:+.4f}%" if diff_oo_futures_pct is not None else "N/A"
|
|
|
- latest_values_for_table[
|
|
|
- "diff_spot_vs_futures_rfc_sol_percentage"] = f"{diff_spot_futures_pct:+.4f}%" if diff_spot_futures_pct is not None else "N/A"
|
|
|
+ # latest_values_for_table["diff_oo_vs_futures_rfc_sol_percentage"] = f"{diff_oo_futures_pct:+.4f}%" if diff_oo_futures_pct is not None else "N/A" # 注释
|
|
|
+ # latest_values_for_table["diff_spot_vs_futures_rfc_sol_percentage"] = f"{diff_spot_futures_pct:+.4f}%" if diff_spot_futures_pct is not None else "N/A" # 注释
|
|
|
|
|
|
latest_values_for_table["oo_error"] = oo_err
|
|
|
latest_values_for_table["gate_spot_error"] = spot_err
|
|
|
- latest_values_for_table["gate_futures_error"] = futures_err
|
|
|
+ # latest_values_for_table["gate_futures_error"] = futures_err # 注释
|
|
|
latest_values_for_table["binance_sol_error"] = binance_err
|
|
|
latest_values_for_table["last_updated"] = fetch_time_full
|
|
|
|
|
|
print(
|
|
|
- f"{fetch_time_chart} Fetch | OO_RFC/SOL:{'OK' if oo_rfc_sol_price else 'F'} | Spot_RFC/SOL:{'OK' if spot_rfc_sol_price else 'F'} | Fut_RFC/SOL:{'OK' if futures_rfc_sol_price else 'F'} | SOL/USDT:{'OK' if sol_usdt_price else 'F'}")
|
|
|
-
|
|
|
+ f"{fetch_time_chart} Fetch | OO_RFC/SOL:{'OK' if oo_rfc_sol_price else 'F'} | Spot_RFC/SOL:{'OK' if spot_rfc_sol_price else 'F'} | SOL/USDT:{'OK' if sol_usdt_price else 'F'}")
|
|
|
time.sleep(REFRESH_INTERVAL_SECONDS)
|
|
|
|
|
|
|
|
|
@app.route('/')
|
|
|
def index_plotly():
|
|
|
- target_asset = latest_values_for_table["target_asset_symbol"] # RFC
|
|
|
- return render_template('index_plotly_sol.html', # Use a new template name to avoid confusion
|
|
|
+ target_asset = latest_values_for_table["target_asset_symbol"]
|
|
|
+ return render_template('index_plotly_sol_spot_only.html',
|
|
|
target_asset=target_asset,
|
|
|
spot_pair_usdt=GATEIO_SPOT_PAIR_RFC_USDT,
|
|
|
- futures_contract_usdt=GATEIO_FUTURES_CONTRACT_RFC_USDT,
|
|
|
sol_usdt_pair_binance=BINANCE_SOL_USDT_PAIR,
|
|
|
refresh_interval_ms=REFRESH_INTERVAL_SECONDS * 1000)
|
|
|
|
|
|
@@ -258,7 +237,7 @@ def get_plotly_chart_data():
|
|
|
"diff_chart": json.loads(json.dumps(fig, cls=PlotlyJSONEncoder))})
|
|
|
|
|
|
times = [p['time'] for p in points]
|
|
|
- target_asset_symbol = latest_values_for_table["target_asset_symbol"] # RFC
|
|
|
+ target_asset_symbol = latest_values_for_table["target_asset_symbol"]
|
|
|
|
|
|
fig_prices = go.Figure()
|
|
|
fig_prices.add_trace(
|
|
|
@@ -269,10 +248,7 @@ def get_plotly_chart_data():
|
|
|
name=f'Gate Spot ({GATEIO_SPOT_PAIR_RFC_USDT} → RFC/SOL)',
|
|
|
line=dict(color='rgb(255, 99, 132)'),
|
|
|
hovertemplate=f'<b>Gate Spot (RFC/SOL)</b><br>Time: %{{x}}<br>Price: %{{y:.8f}} SOL<extra></extra>'))
|
|
|
- fig_prices.add_trace(go.Scatter(x=times, y=[p['futures_rfc_sol'] for p in points], mode='lines',
|
|
|
- name=f'Gate Futures ({GATEIO_FUTURES_CONTRACT_RFC_USDT} → RFC/SOL)',
|
|
|
- line=dict(color='rgb(54, 162, 235)'),
|
|
|
- hovertemplate=f'<b>Gate Futures (RFC/SOL)</b><br>Time: %{{x}}<br>Price: %{{y:.8f}} SOL<extra></extra>'))
|
|
|
+ # fig_prices.add_trace(go.Scatter(x=times, y=[p['futures_rfc_sol'] for p in points], mode='lines', name=f'Gate Futures ({GATEIO_FUTURES_CONTRACT_RFC_USDT} → RFC/SOL)', line=dict(color='rgb(54, 162, 235)'), hovertemplate=f'<b>Gate Futures (RFC/SOL)</b><br>Time: %{{x}}<br>Price: %{{y:.8f}} SOL<extra></extra>')) # 注释
|
|
|
|
|
|
fig_prices.update_layout(title_text=f'{target_asset_symbol}/SOL 价格历史', xaxis_title='时间',
|
|
|
yaxis_title=f'价格 (1 {target_asset_symbol} = X SOL)', legend_title_text='平台',
|
|
|
@@ -282,14 +258,10 @@ def get_plotly_chart_data():
|
|
|
fig_diffs.add_trace(go.Scatter(x=times, y=[p['diff_oo_spot_rfc_sol'] for p in points], mode='lines',
|
|
|
name=f'OO vs Spot (RFC/SOL)', line=dict(color='rgb(255, 159, 64)'),
|
|
|
hovertemplate=f'<b>OO vs Spot (RFC/SOL)</b><br>Time: %{{x}}<br>Diff: %{{y:+.4f}}%<extra></extra>'))
|
|
|
- fig_diffs.add_trace(go.Scatter(x=times, y=[p['diff_oo_futures_rfc_sol'] for p in points], mode='lines',
|
|
|
- name=f'OO vs Futures (RFC/SOL)', line=dict(color='rgb(153, 102, 255)'),
|
|
|
- hovertemplate=f'<b>OO vs Futures (RFC/SOL)</b><br>Time: %{{x}}<br>Diff: %{{y:+.4f}}%<extra></extra>'))
|
|
|
- fig_diffs.add_trace(go.Scatter(x=times, y=[p['diff_spot_futures_rfc_sol'] for p in points], mode='lines',
|
|
|
- name=f'Spot vs Futures (RFC/SOL)', line=dict(color='rgb(75, 192, 75)'),
|
|
|
- hovertemplate=f'<b>Spot vs Futures (RFC/SOL)</b><br>Time: %{{x}}<br>Diff: %{{y:+.4f}}%<extra></extra>'))
|
|
|
-
|
|
|
- fig_diffs.update_layout(title_text=f'{target_asset_symbol}/SOL 价差百分比历史', xaxis_title='时间',
|
|
|
+ # fig_diffs.add_trace(go.Scatter(x=times, y=[p['diff_oo_futures_rfc_sol'] for p in points], mode='lines', name=f'OO vs Futures (RFC/SOL)', line=dict(color='rgb(153, 102, 255)'), hovertemplate=f'<b>OO vs Futures (RFC/SOL)</b><br>Time: %{{x}}<br>Diff: %{{y:+.4f}}%<extra></extra>')) # 注释
|
|
|
+ # fig_diffs.add_trace(go.Scatter(x=times, y=[p['diff_spot_futures_rfc_sol'] for p in points], mode='lines', name=f'Spot vs Futures (RFC/SOL)', line=dict(color='rgb(75, 192, 75)'), hovertemplate=f'<b>Spot vs Futures (RFC/SOL)</b><br>Time: %{{x}}<br>Diff: %{{y:+.4f}}%<extra></extra>')) # 注释
|
|
|
+
|
|
|
+ fig_diffs.update_layout(title_text=f'{target_asset_symbol}/SOL 价差百分比历史 (OO vs Spot)', xaxis_title='时间',
|
|
|
yaxis_title='价差 (%)', legend_title_text='对比', yaxis_zeroline=True,
|
|
|
hovermode='x unified')
|
|
|
|
|
|
@@ -302,15 +274,15 @@ def get_plotly_chart_data():
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
print("应用启动...")
|
|
|
- asset_symbol = GATEIO_SPOT_PAIR_RFC_USDT.split('_')[0] # RFC
|
|
|
+ asset_symbol = GATEIO_SPOT_PAIR_RFC_USDT.split('_')[0]
|
|
|
print(f"目标资产: {asset_symbol}")
|
|
|
print(
|
|
|
f"OpenOcean: {asset_symbol}/SOL (通过 {IN_TOKEN_ADDRESS_SOLANA[-6:]}...SOL / {OUT_TOKEN_ADDRESS_SOLANA[-6:]}...{asset_symbol})")
|
|
|
print(f"Gate.io 现货: {GATEIO_SPOT_PAIR_RFC_USDT} (将转换为 {asset_symbol}/SOL)")
|
|
|
- print(f"Gate.io 期货: {GATEIO_FUTURES_CONTRACT_RFC_USDT} (将转换为 {asset_symbol}/SOL)")
|
|
|
+ # print(f"Gate.io 期货: {GATEIO_FUTURES_CONTRACT_RFC_USDT} (将转换为 {asset_symbol}/SOL)") # 注释
|
|
|
print(f"币安转换汇率: {BINANCE_SOL_USDT_PAIR}")
|
|
|
|
|
|
data_thread = threading.Thread(target=update_data_for_plotly_and_table, daemon=True)
|
|
|
data_thread.start()
|
|
|
print(f"Flask 服务将在 http://0.0.0.0:5000 上运行 (刷新间隔: {REFRESH_INTERVAL_SECONDS}s)")
|
|
|
- app.run(debug=False, host='0.0.0.0', port=5000, use_reloader=False)
|
|
|
+ app.run(debug=False, host='0.0.0.0', port=5000, use_reloader=False)
|