Bitcoin Forum
November 08, 2024, 10:30:00 PM *
News: Latest Bitcoin Core release: 28.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Arbitraggio Defi  (Read 211 times)
JGreg96 (OP)
Full Member
***
Offline Offline

Activity: 602
Merit: 144



View Profile
June 19, 2022, 10:11:39 PM
 #1

Apro questo thread principalmente per 2 motivi:
  • In giro c' è veramente poca documentazione riguardo questo argomento
  • Volevo condividere la mia esperienza

Partiamo con la documentazione che ho trovato nell' internet:

Cos' è l' arbitraggio

Triangular Arbitrage
Arbitrage on Dex

Modello economico di UniswapV2 e relativi contratti e funzioni

UniswapV2
Price Impact

Documentazione un po più avanzata

Dex Arbitrage Solidity
Cyclic Arbitrage
Graph on Arbitrage

Per avere un sistema di arbitraggio funzionante quindi, è necessario sviluppare 2 blocchi principali
  • Uno strumento che cerca le opportunità di arbitraggio
  • Uno strumento che, attivato dal precedente, processa le operazioni

La parte interessante dell' arbitraggio in Defi è che il secondo strumento può essere sviluppato interamente come uno smart contract con tutti i benefici che ne conseguono.

Inutile dire che l' arbitraggio manuale è un' opzione poco perseguibile quindi per entrambi gli strumenti si dovrà ricorrere a linguaggi di programmazione (personalmente ho utilizzato python con web3py e solidity), inoltre è possibile dividere le classi di arbitraggio in 2 categorie in base al numero di coin scambiate:
  • A 2 vie: A->B  B->A
  • A 3 vie: A->B  B->C  C->A

Infine è necessario precisare che il resto della trattazione assume come "unico" Dex di riferimento i derivati di UniswapV2. Nulla vieta di estendere anche ad altri Dex non uniswaplike ma i meccanismi potrebbero essere diversi.

Ricerca di opportunità di arbitraggio
Ci sono diversi metodi per eseguire questa operazione, personalmente ne ho testati 2.
Il primo consiste nell' identificare gli address dei pair corrispondenti ai token di interesse e successivamente sfruttare la function balanceOf dei token ERC20 inserendo l' address del pair (o pool). Quindi nel codice avremo una costruzione del tipo:
Code:
Contract=web3.eth.Contract(address="tokenA",abi="L' abi ERC20")  //Inizializzo il contratto del tokenA
Balance1=Contract.functions.balanceOf("pair").call()   // "Contract" è un oggetto con dei metodi (functions) definite dall' abi e chiamiamo (call) la function balanceOf per ottenere l' ammontare di tokenA presenti nella pool tokenA-tokenB
Nota: Pair e Pool sono la stessa cosa: in UniswapV2 vengono chiamati Pair, in uniswapV3 Pool

L' altro metodo invece sfrutta la function getReserves del contratto del pair. Questa function non ha input e ritorna l' ammontare dei token e l' ultimo blocco di aggiornamento della pair. Attenzione: questa function ritorna le riserve R0 e R1 dei token0 e token1 del pair che sono hardcoded nel contratto del pair. Serve dunque mappare correttamente (token0,token1) con (tokenA,tokenB) per avere le riserve corrette RA e RB. Nel codice:
Code:
//Inizializzo il contratto
Contract=web3.eth.Contract(address=pair,abi=abi_pair)
// Ottengo i token0 e token1
token0=Contract.functions.token0().call()
token1=Contract.functions.token1().call()
//Prendo le riserve
(R0,R1,BLK)=Contract.functions.getReserves().call()
//indicizzo correttamente le riserve
if token0==tokenA
     RA=R0; RB=R1
else
     RA=R1; RB=R0

Indipendentemente dal procedimento scelto alla fine avremo le riserve (o balance) della pool e quindi è necessario calcolare il prezzo. Purtroppo entrambi i  metodi ritorano un intero ma i token ERC20 possono avere decimali diversi quindi prima di calcolare il prezzo è necessario scalare le riserve:

Code:
Contract=web3.eth.Contract(address="tokenA",abi="L' abi ERC20")  //Inizializzo il contratto del tokenA
decimale=Contract.functions.decimals().call()
RA_=RA/10^decimale
Fatta la stessa procedura anche per il token B è possibile calcolare il prezzo dei token della pool come (RA_/RB_) oppure come (RB_/RA_)
Iterando per diversi Pair (ovvero per diversi dex) con gli stessi tokenA/tokenB è possibile avere i diversi prezzi ovvero valutare l' opportunità.

Adesso, per semplicità concentriamoci sull' arbitraggio a 2 vie in cui ricapitolando, è possibile costruirsi un insieme di prezzi semplicemente vedendo le riserve delle pool tokenA-tokenB sui vari dex.
In questo insieme estraiamo banalmente il massimo e il minimo e assumiamo di partire dal tokenA e che i prezzi siano calcolati secondo RB_/RA_.
In questo modo è abbastanza chiaro che il primo swap dovrà essere fatto sul dex con prezzo massimo (in quanto è quello che dà più tokenB) mentre lo swap di chiusura sarà fatto su quello con prezzo minimo (a parità di tokenB è quello che mi dà più tokenA)
In questo modo si riesce ad identificare un percorso da seguire in cui valutare se è possibile fare l' arbitraggio o meno.

Opportunità di arbitraggio a 2 vie

Dalla documentazione di uniswap è chiaro che tutti i dex in questione hanno il modello x*y=k. Questo significa che, identificate come Lx e Ly le riserve rispettivamente dei token x e y. in uno swap, la quantità Lx*Ly deve rimanere costante e uguale a k. Questo significa che è possibile calcolare la quantità Y di token y che si ricevono assumendo di swappare una quantità X di token x. Infatti la nuova liquidità sarà Lx+X -> Ly_new=k/(Lx+X) -> Y=Ly-Ly_new
in definitiva è possibile esprimere Y come Y=X*Ly/(Lx+X)

Tramite questa formula è possibile proseguire con lo swap di ritorno (ovvero X'=Y*Lx'/(Ly'+Y)) e l' arbitraggio sarà profittevole solo se P=X'-X-fee>0

Questo è il primo traguardo: quindi ora vi basta impostare un ammontare X -> ottenere le liquidità -> prendere massimo e minimo -> calcolare il profitto e vedere se è maggiore di 0. In caso di esito positivo farete eseguire gli swap dallo smart contract.

Per chi è un po più perfezionista, è possibile calcolare l' ammontare di X che massimizza il profitto P=X'-X-fee:

Infatti P è una frazione nella forma (-aX^2+bX+c)/(aX+c/fee) dove a,b,c sono quantità che dipendono dalle liquidità delle 2 pool e dalle fee.
E' dunque possibile calcolare la derivata di P rispetto ad X -> porla uguale a 0 ed ottenere dunque il valore di X che massimizza la funzione P.

Opportunità di arbitraggio a 3 vie
Per quanto riguarda l' arbitraggio a 3 vie il procedimento è molto più complesso in quanto la discriminante max min non può essere usata nello stesso modo quindi sono necessarie altre tecniche che però non ho ancora personalmente sperimentato

Esecuzione degli swap
Come accennato precedentemente una volta trovato un percorso profittevole, è necessario eseguire le operazioni e quindi mandare le transazioni. L' idea di base è incorporare tutte le transazioni in una utilizzando uno smart contract.
Per farlo è necessario importare l' interfaccia del router di UniswapV2 e creare una function nel contratto che esegua le operazioni.
Questa parte è spiegata molto bene (per l' arbitraggio a 2 vie) in questo link presente anche nella documentazione. In caso di arbitraggio a 3 vie basta aggiungere il terzo swap.

Miglioramenti
Il procedimento sopra vuole dare delle linee guida su come approcciare la creazione di un sistema di arbitraggio automatizzato ma chiaramente ha ampi margini di miglioramento. Per definizione, l' arbitraggio è profittevole solo ai primi (o al primo) che eseguono gli swap, quindi la velocità è tutto: è necessario ridurre i tempi di raccolta delle info, del processamento e del relativo input. In Defi la velocità è misurata in blocchi convalidati infatti generalmente, in situazione di equilibrio, non c' è un percorso profittevole -> serve dunque una transazione che sbilancia il mercato che sarà convalidatà la blocco B1 quindi più si è vicini al blocco B1 (incluso) e più è probabile che l' arbitraggio abbia successo.
  • Riuscire a convalidare la transazione di arbitraggio lo stesso blocco di quella che sbilancia il mercato è dunque il miglior modo possibile, ma per farlo è necessario valutare le pending transactions -> simulare le nuove riserve -> da quelle calcolare la profittabilità. Il tutto in un lasso di tempo che va da quando la transazione è in pending a quando viene confermata.
  • Utilizzare la teoria dei grafi per trovare percorsi profittevoli. In rete è presente diversa documentazione a riguardo (nessuna pappa pronta ma sempre linee guida) e se riesco a ritagliare un po di spazio vorrei dedicargli del tempo
  • Riuscire ad indentificare i token con fee sugli swap (tipo buyback,transfer fee ecc..) e valutarne la profittabilità

Parere personale
Da quello che ho visto, ce ne sono parecchi di bot di arbitraggio che operano tra i vari dex. Utilizzano metodi anche a volte diversi, per esempio alcuni utilizzano aggregatori tipo 1inch con i chitoken, altri invece non fanno un arbitraggio in senso stretto ma appena vedono in pending una transazione "grossa" rispetto la liquidità della pool, si muovono sia prima che dopo la transazione (nello stesso blocco).
Quindi è un mondo molto competitivo dove però i margini possono essere anche molto molto alti.

BTCBTCBTC
JGreg96 (OP)
Full Member
***
Offline Offline

Activity: 602
Merit: 144



View Profile
August 26, 2023, 06:37:45 PM
 #2

Sembra che l' interesse per questo tipo di operatività sia aumentato notevolmente con quello che ora viene chiamato MEV Bot.

Personalmente ho trascorso parecchio tempo cercando di includere i miglioramenti che avevo descritto nei vari punti. Ci sono riuscito ma nel frattempo la competizione aumentava e le strade percorribili erano sempre meno. è stata secondo me un esperienza enormemente formativa perchè mi ha permesso di imparare diversi linguaggi di programmazione (python, javascript, solidity,...) applicandoli direttamente in un contesto blockchain. Il livello di profondità tecnica che si raggiunge (per essere competitivi) è decisamente molto alto e consente di scoprire sfaccettature sempre più sottili che fanno poi la differenza.

Appena riuscirò a ritagliarmi una finestra vorrei completare la "mini guida - esperienza" su quello che ho fatto e sviluppato.

A grandi linee comunque:

  • Grafi: utilizzo della libreria networkx in python per la creazione di un grafo direzionale. I nodi sono le coin, i rami contengono le informazioni sulle riserve delle pool (tutte le pool su più dex). Si parte da un nodo pivot e si trovano tutti i percorsi chiusi in questo grafo. La valutazione del prezzo la si fa ciclando su tutti i loop.
  • Convalidare nello stesso blocco: è stata la sfida più difficile. Bisogna affittare un nodo personale, migrare il codice in javascript (web3py non sembra vedere le pending transactions, inoltre i promise di JS aiutano) e adattarlo al fatto di leggere le pending transaction e quindi ricalcolarsi i balance manualmente. Inoltre la gestione dei grafi in JS è possibile ma molto più macchinosa (ogni linguaggio ha le sue peculiarità). Insomma a livello di programmazione è quasi un massacro.

Nota: di solito le guide che si trovano in giro non spiegano come cercare opportunità, ma spiegano come vedere se è profittevole e fare le transazioni. Se viene pensata per una coppia singola in un singolo DEX è teoricamente fattibile (non praticamente), ma enormemente limitante rispetto alle (quasi infinite) combinazioni/possibilità che ci sarebbero. Quindi sono praticamente inutili e andrebbero generalizzate/adattate.

BTCBTCBTC
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!