Skip to content

Commit

Permalink
Merge branch 'pool_finder_period' of https://github.com/bancorprotoco…
Browse files Browse the repository at this point in the history
…l/fastlane-bot into pool_finder_period
  • Loading branch information
barak manos committed May 13, 2024
2 parents 0334a3f + fc94895 commit d01d8b3
Show file tree
Hide file tree
Showing 11 changed files with 37 additions and 119 deletions.
7 changes: 4 additions & 3 deletions fastlane_bot/config/multicaller.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
All rights reserved.
Licensed under MIT.
"""
from typing import Callable, Any, List, Dict
from typing import Any, List, Dict

from eth_abi import decode
from web3.contract.contract import ContractFunction

from fastlane_bot.data.abi import MULTICALL_ABI

Expand Down Expand Up @@ -45,10 +46,10 @@ class MultiCaller:

def __init__(self, web3: Any, multicall_contract_address: str):
self.multicall_contract = web3.eth.contract(abi=MULTICALL_ABI, address=multicall_contract_address)
self.contract_calls: List[Callable] = []
self.contract_calls: List[ContractFunction] = []
self.output_types_list: List[List[str]] = []

def add_call(self, call: Callable):
def add_call(self, call: ContractFunction):
self.contract_calls.append({'target': call.address, 'callData': call._encode_transaction_data()})
self.output_types_list.append([collapse_if_tuple(item) for item in call.abi['outputs']])

Expand Down
3 changes: 3 additions & 0 deletions fastlane_bot/events/exchanges/balancer.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,6 @@ async def get_tkn_n(self, address: str, contract: Contract, event: Any, index: i
tokens = pool_balances[0]
token_balances = pool_balances[1]
return token_balances[index]

def get_pool_func_call(self, addr1, addr2):
raise NotImplementedError
3 changes: 3 additions & 0 deletions fastlane_bot/events/exchanges/bancor_pol.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,6 @@ def save_strategy(
cid=cid,
block_number=block_number,
)

def get_pool_func_call(self, addr1, addr2):
raise NotImplementedError
3 changes: 3 additions & 0 deletions fastlane_bot/events/exchanges/bancor_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,6 @@ async def get_tkn1(self, address: str, contract: Contract, event: Event) -> str:

async def get_anchor(self, contract: Contract) -> str:
return await contract.caller.anchor()

def get_pool_func_call(self, addr1, addr2):
raise NotImplementedError
3 changes: 3 additions & 0 deletions fastlane_bot/events/exchanges/bancor_v3.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,6 @@ async def get_tkn1(self, address: str, contract: Contract, event: Event) -> str:
if event.args["pool"] != self.BNT_ADDRESS
else event.args["tkn_address"]
)

def get_pool_func_call(self, addr1, addr2):
raise NotImplementedError
4 changes: 4 additions & 0 deletions fastlane_bot/events/exchanges/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ async def get_fee(address: str, contract: AsyncContract) -> float:
"""
pass

@abstractmethod
def get_pool_func_call(self, addr1, addr2, *args, **kwargs):
...

@staticmethod
@abstractmethod
async def get_tkn0(address: str, contract: AsyncContract, event: Any) -> str:
Expand Down
3 changes: 3 additions & 0 deletions fastlane_bot/events/exchanges/carbon_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,6 @@ def save_strategy(
),
block_number=block_number,
)

def get_pool_func_call(self, addr1, addr2):
raise NotImplementedError
63 changes: 5 additions & 58 deletions fastlane_bot/modes/base_triangle.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,10 @@
from fastlane_bot.modes.base import ArbitrageFinderBase
from fastlane_bot.tools.cpc import T

@staticmethod
def sort_pairs(pairs):
# Clean up the pairs alphabetically
return ["/".join(sorted(pair.split('/'))) for pair in pairs]

@staticmethod
def flatten_nested_items_in_list(nested_list):
# unpack nested items
flattened_list = []
Expand All @@ -36,7 +34,6 @@ def flatten_nested_items_in_list(nested_list):
flattened_list.append(flat_list)
return flattened_list

@staticmethod
def get_triangle_groups(flt, x_y_pairs):
# Get groups of triangles that conform to (flt/x , x/y, y/flt) where x!=y
triangle_groups = []
Expand All @@ -45,7 +42,6 @@ def get_triangle_groups(flt, x_y_pairs):
triangle_groups += [("/".join(sorted([flt,x])), pair, "/".join(sorted([flt,y])))]
return triangle_groups

@staticmethod
def get_triangle_groups_stats(triangle_groups, all_relevant_pairs_info):
# Get the stats on the triangle group cohort for decision making
valid_carbon_triangles = []
Expand Down Expand Up @@ -250,7 +246,7 @@ def get_analysis_set_per_flt(self, flt, valid_triangles, all_relevant_pairs_info
return flt_triangle_analysis_set

def get_comprehensive_triangles(
self, flashloan_tokens: List[str], CCm: Any, arb_mode: str
self, flashloan_tokens: List[str], CCm: Any
) -> Tuple[List[str], List[Any]]:
"""
Get comprehensive combos for triangular arbitrage
Expand All @@ -261,8 +257,6 @@ def get_comprehensive_triangles(
List of flashloan tokens
CCm : object
CCm object
arb_mode : str
Arbitrage mode
Returns
-------
Expand Down Expand Up @@ -306,63 +300,16 @@ def get_comprehensive_triangles(
combos.extend(flt_triangle_analysis_set)
return combos

@staticmethod
def get_mono_direction_carbon_curves(
miniverse: List[Any], trade_instructions_df: pd.DataFrame, token_in: str=None
) -> List[Any]:
"""
Get mono direction carbon curves for triangular arbitrage
Parameters
----------
miniverse : list
List of miniverses
token_in : str
Token in
trade_instructions_df : DataFrame
Trade instructions dataframe
Returns
-------
mono_direction_carbon_curves : list
List of mono direction carbon curves
"""

if token_in is None:
columns = trade_instructions_df.columns
check_nan = trade_instructions_df.copy().fillna(0)
first_bancor_v3_pool = check_nan.iloc[0]
second_bancor_v3_pool = check_nan.iloc[1]

for idx, token in enumerate(columns):
if token == T.BNT:
continue
if first_bancor_v3_pool[token] < 0:
token_in = token
break
if second_bancor_v3_pool[token] < 0:
token_in = token
break

wrong_direction_cids = []
for idx, row in trade_instructions_df.iterrows():
if (row[token_in] < 0) and ("-0" in idx or "-1" in idx):
wrong_direction_cids.append(idx)

return [curve for curve in miniverse if curve.cid not in wrong_direction_cids]
def build_pstart(self, CCm, tkn0list, tkn1):
tkn0list = [x for x in tkn0list if x not in [tkn1]]
pstart = {}
for tkn0 in tkn0list:
try:
price = CCm.bytknx(tkn0).bytkny(tkn1)[0].p
pstart[tkn0] = CCm.bytknx(tkn0).bytkny(tkn1)[0].p
except:
try:
price = 1/CCm.bytknx(tkn1).bytkny(tkn0)[0].p
pstart[tkn0] = 1/CCm.bytknx(tkn1).bytkny(tkn0)[0].p
except Exception as e:
print(str(e))
self.ConfigObj.logger.debug(f"[pstart build] {tkn0} not supported. w {tkn1} {str(e)}")
pstart[tkn0]=price
self.ConfigObj.logger.info(f"[pstart build] {tkn0}/{tkn1} price error {e}")
pstart[tkn1] = 1
return pstart
return pstart
34 changes: 4 additions & 30 deletions fastlane_bot/modes/triangle_multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,31 +33,23 @@ def find_arbitrage(self, candidates: List[Any] = None, ops: Tuple = None, best_p
if candidates is None:
candidates = []

combos = self.get_combos(
self.flashloan_tokens, self.CCm, arb_mode=self.arb_mode
)
combos = self.get_combos(self.flashloan_tokens, self.CCm, arb_mode=self.arb_mode)

for src_token, miniverse in combos:
try:
r = None
CC_cc = CPCContainer(miniverse)
O = MargPOptimizer(CC_cc)
#try:
pstart = self.build_pstart(CC_cc, CC_cc.tokens(), src_token)
r = O.optimize(src_token, params=dict(pstart=pstart)) #debug=True, debug2=True
r = O.optimize(src_token, params=dict(pstart=pstart))
trade_instructions_dic = r.trade_instructions(O.TIF_DICTS)
if len(trade_instructions_dic) < 3:
if trade_instructions_dic is None or len(trade_instructions_dic) < 3:
# Failed to converge
continue
trade_instructions_df = r.trade_instructions(O.TIF_DFAGGR)
trade_instructions = r.trade_instructions()

except Exception as e:
self.ConfigObj.logger.debug(f"[triangle multi] {str(e)}")
continue
if trade_instructions_dic is None:
continue
if len(trade_instructions_dic) < 2:
self.ConfigObj.logger.info(f"[triangle multi] {e}")
continue
profit_src = -r.result

Expand Down Expand Up @@ -92,21 +84,3 @@ def find_arbitrage(self, candidates: List[Any] = None, ops: Tuple = None, best_p
)

return candidates if self.result == self.AO_CANDIDATES else ops

def build_pstart(self, CCm, tkn0list, tkn1):
tkn0list = [x for x in tkn0list if x not in [tkn1]]
pstart = {}
for tkn0 in tkn0list:
try:
price = CCm.bytknx(tkn0).bytkny(tkn1)[0].p
except:
try:
price = 1/CCm.bytknx(tkn1).bytkny(tkn0)[0].p
except Exception as e:
print(str(e))
self.ConfigObj.logger.debug(f"[pstart build] {tkn0} not supported. w {tkn1} {str(e)}")
pstart[tkn0]=price
pstart[tkn1] = 1
return pstart


31 changes: 4 additions & 27 deletions fastlane_bot/modes/triangle_multi_complete.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,30 +30,23 @@ def find_arbitrage(self, candidates: List[Any] = None, ops: Tuple = None, best_p
if candidates is None:
candidates = []

combos = self.get_comprehensive_triangles(
self.flashloan_tokens, self.CCm, arb_mode=self.arb_mode
)
combos = self.get_comprehensive_triangles(self.flashloan_tokens, self.CCm)

for src_token, miniverse in combos:
try:
r = None
CC_cc = CPCContainer(miniverse)
O = MargPOptimizer(CC_cc)
pstart = self.build_pstart(CC_cc, CC_cc.tokens(), src_token)
r = O.optimize(src_token, params=dict(pstart=pstart)) #debug=True, debug2=True, verbose=True
r = O.optimize(src_token, params=dict(pstart=pstart))
trade_instructions_dic = r.trade_instructions(O.TIF_DICTS)
if len(trade_instructions_dic) < 3:
if trade_instructions_dic is None or len(trade_instructions_dic) < 3:
# Failed to converge
continue
trade_instructions_df = r.trade_instructions(O.TIF_DFAGGR)
trade_instructions = r.trade_instructions()

except Exception as e:
self.ConfigObj.logger.debug(f"[triangle multi] {str(e)}")
continue
if trade_instructions_dic is None:
continue
if len(trade_instructions_dic) < 2:
self.ConfigObj.logger.info(f"[triangle multi] {e}")
continue
profit_src = -r.result

Expand Down Expand Up @@ -88,19 +81,3 @@ def find_arbitrage(self, candidates: List[Any] = None, ops: Tuple = None, best_p
)

return candidates if self.result == self.AO_CANDIDATES else ops

def build_pstart(self, CCm, tkn0list, tkn1):
tkn0list = [x for x in tkn0list if x not in [tkn1]]
pstart = {}
for tkn0 in tkn0list:
try:
pstart[tkn0] = CCm.bytknx(tkn0).bytkny(tkn1)[0].p
except:
try:
pstart[tkn0] = 1/CCm.bytknx(tkn1).bytkny(tkn0)[0].p
except Exception as e:
self.ConfigObj.logger.info(f"[pstart build] {tkn0} not supported. w {tkn1} {e}")
pstart[tkn1] = 1
return pstart


2 changes: 1 addition & 1 deletion fastlane_bot/tests/test_064_TestMultiAllMode.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ def test_test_expected_output():

assert len(r) >= 25, f"[NBTest64 TestMultiPairwiseAll Mode] Expected at least 25 arbs, found {len(r)}"
assert multi_carbon_count > 0, f"[NBTest64 TestMultiPairwiseAll Mode] Not finding arbs with multiple Carbon curves."
# assert carbon_wrong_direction_count == 0, f"[NBTest64 TestMultiPairwiseAll Mode] Expected all Carbon curves to have the same tkn in and tkn out. Mixing is currently not supported."
assert carbon_wrong_direction_count == 6, f"[NBTest64 TestMultiPairwiseAll Mode] Expected 6 Carbon curves to be in the opposite direction."
# -


0 comments on commit d01d8b3

Please sign in to comment.