forked from zekita/paradex-neutral
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
147 lines (113 loc) · 4.56 KB
/
main.py
File metadata and controls
147 lines (113 loc) · 4.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
from paradex_py import Paradex
from paradex_py.common.order import Order, OrderSide, OrderType
import os
from dotenv import load_dotenv
import time
import requests
import traceback
from decimal import Decimal, ROUND_DOWN
load_dotenv()
paradex = Paradex(
env="prod", # Correto: string, não enum
l1_address=os.getenv("L1_ADDRESS"),
l1_private_key=os.getenv("L1_PRIVATE_KEY")
)
# Configurações
DELTA_THRESHOLD = 0.0000001 # Ignora desequilíbrios pequenos
SLEEP_INTERVAL = 5 # Intervalo entre execuções (em segundos)
def infer_hedge_market(base_asset):
try:
all_markets = requests.get("https://api.prod.paradex.trade/v1/markets").json()["results"]
except Exception as e:
print(f"[!] Erro ao buscar lista de mercados: {e}")
return None
for m in all_markets:
if m.get("asset_kind") == "PERP" and m.get("base_currency") == base_asset:
return m.get("symbol")
return None
def get_market_delta(market):
url = f"https://api.prod.paradex.trade/v1/markets/summary?market={market}"
try:
response = requests.get(url)
if response.status_code == 200:
results = response.json().get("results", [])
if results and "greeks" in results[0]:
return float(results[0]["greeks"].get("delta", 0))
except Exception as e:
print(f"[!] Erro ao buscar gregos de {market}: {e}")
return 0.0
def get_positions():
try:
res = paradex.api_client.fetch_positions()
return res.get("results", [])
except Exception as e:
print(f"[!] Erro ao buscar posições: {e}")
return []
def calculate_total_delta(positions):
time.sleep(2)
total_deltas = {}
for pos in positions:
market = pos.get("market", "")
signed_size = float(pos.get("size", 0))
base = market.split("-")[0]
delta = get_market_delta(market)
contribution = signed_size * delta
total_deltas[base] = total_deltas.get(base, 0.0) + contribution
# Seleciona o ativo com maior exposição (módulo do delta)
if not total_deltas:
return None, None
best_base = max(total_deltas.items(), key=lambda x: abs(x[1]))[0]
return round(total_deltas[best_base], 6), best_base
def hedge(delta, hedge_market, all_markets):
if abs(delta) < DELTA_THRESHOLD:
print(f"Δ {delta:.6f} → dentro da tolerância. Nenhuma ação.")
return
try:
# Encontra info do mercado com base no symbol
market_info = next((m for m in all_markets if m.get("symbol") == hedge_market), None)
if not market_info:
print(f"[!] Mercado '{hedge_market}' não encontrado. Ordem cancelada.")
return
side = OrderSide.Sell if delta > 0 else OrderSide.Buy
raw_size = Decimal(str(abs(delta)))
# Usa o incremento correto do par (ex: 1, 0.01, 0.001...)
size_increment = Decimal(market_info.get("order_size_increment", "0.001"))
size = raw_size.quantize(size_increment, rounding=ROUND_DOWN)
if size < size_increment:
print(f"[!] Size {size} abaixo do mínimo permitido ({size_increment}). Ordem não enviada.")
return
order = Order(
market=hedge_market,
order_type=OrderType.Market,
order_side=side,
size=size
)
print("[DEBUG] Ordem construída:")
print(order.__dict__)
resp = paradex.api_client.submit_order(order)
print(f"[+] Ordem hedge enviada: {side.name} {size} no {hedge_market}")
except Exception as e:
print(f"[!] Erro ao enviar ordem de hedge: {e}")
traceback.print_exc()
def main():
print("===> Iniciando loop de hedge delta-neutro <===")
while True:
try:
positions = get_positions()
delta, base = calculate_total_delta(positions)
if delta is None or base is None:
print("[!] Nenhuma posição com delta relevante. Pulando...")
continue
hedge_market = infer_hedge_market(base)
if hedge_market is None:
print(f"[!] Nenhum PERP correspondente encontrado para {base}. Pulando...")
continue
all_markets = paradex.api_client.fetch_markets()["results"] # pega atualizado
print(f"Δ total: {delta:.6f}")
hedge(delta, hedge_market, all_markets)
except Exception as e:
print(f"[!] Erro no loop principal: {type(e).__name__}: {e}")
traceback.print_exc()
time.sleep(SLEEP_INTERVAL)
if __name__ == "__main__":
main()