Skip to content

Commit e4abe93

Browse files
chore: improve logging in strategies
1 parent effa57c commit e4abe93

File tree

10 files changed

+142
-75
lines changed

10 files changed

+142
-75
lines changed

packages/packages.json

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
22
"dev": {
33
"custom/valory/merkl_pools_search/0.1.0": "bafybeihg3shkrvx7yzrqenjow23ebcl5xskrzrqkj47er2z47xhhs2z6ma",
4-
"custom/valory/asset_lending/0.1.0": "bafybeiejhhvualyp7xokskpyc3ki2k3u7v42qwe3hva36pgph3d2qwn6zu",
4+
"custom/valory/asset_lending/0.1.0": "bafybeigjrvck43iqoh427ziph7ov4m2kg332prbwybxkepjfv536yczxky",
55
"custom/valory/max_apr_selection/0.1.0": "bafybeihk4ehqcwlwlqdl2ifkyz2hfwfs232fs3n5rt64wfrobjt5ot2woy",
6-
"custom/valory/balancer_pools_search/0.1.0": "bafybeihzodbkd4vatcphzu4672x5nitymhchbecvew7rpbu3hteh5rgyai",
6+
"custom/valory/balancer_pools_search/0.1.0": "bafybeid7tyebp2cmnkclqysnhjufppf7fggbpl7sigqinuigtxaj74fc3m",
77
"custom/valory/uniswap_pools_search/0.1.0": "bafybeib7ibbjnhycdzyd3ind2no3sn77wxnlde3etxzh65lycj6obodq2e",
88
"contract/valory/balancer_weighted_pool/0.1.0": "bafybeidthw5afkeswxqockblrzzgmeiwhqgukytyr4veaf4ok66qv3zjfe",
99
"contract/valory/balancer_vault/0.1.0": "bafybeibd3luq5ghhnhrkzeaytinwklnajk4urkd6ihbd26swziqfkjsfeq",
@@ -14,10 +14,10 @@
1414
"contract/valory/staking_token/0.1.0": "bafybeic4ug4p22q4hsh5z4hhjrishvnswino2fsleqsgdxlusd5h2x5hwy",
1515
"contract/valory/staking_activity_checker/0.1.0": "bafybeiajn7vzmxkiqoruknqh3heb3qxlflukibalxkm6zxdvmazdoou7ou",
1616
"contract/valory/sturdy_yearn_v3_vault/0.1.0": "bafybeigmc3f5xqrcdjakandeang56vtzp5qcqbjk4fven5d2h6t272kmpu",
17-
"skill/valory/liquidity_trader_abci/0.1.0": "bafybeidneasv2yf3uaujlvtnj7sphkc3bnlfzb4dmhxhivnarpavsqorle",
18-
"skill/valory/optimus_abci/0.1.0": "bafybeicilmohuxn7bwzlvcdg6owii64vzyscqalswsdnxpngbqoxvbkjsq",
19-
"agent/valory/optimus/0.1.0": "bafybeic53ieta7mzxkwhzobautcueb2vrsmvsdopvpigs55sgjp5lqrjnq",
20-
"service/valory/optimus/0.1.0": "bafybeicio3fqqntuzj73h6r5csxt77ybvaptd7iv67qp7rpesguwdor35a"
17+
"skill/valory/liquidity_trader_abci/0.1.0": "bafybeia6vi5ojpzuziev63nyubllrccvkr6kiav73khdx7lf7npwx6pt2m",
18+
"skill/valory/optimus_abci/0.1.0": "bafybeiffnvbgab3rkaik4t7p3q32nrgilhpgetkioqj76f7d3rhsopbhgi",
19+
"agent/valory/optimus/0.1.0": "bafybeihustqanr4dalj3z2zey2qe4d36hlqo6vd55hqlafbldvswuheqx4",
20+
"service/valory/optimus/0.1.0": "bafybeigqbfyycwqpnkydtrttazsxd4ns3xdylgcbl74nbv72cyucmgobbu"
2121
},
2222
"third_party": {
2323
"protocol/open_aea/signing/1.0.0": "bafybeihv62fim3wl2bayavfcg3u5e5cxu3b7brtu4cn5xoxd6lqwachasi",

packages/valory/agents/optimus/aea-config.yaml

+5-5
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,18 @@ protocols:
3636
skills:
3737
- valory/abstract_abci:0.1.0:bafybeif2naoydlrqkdpnig34uejedwgurjwyvmbpcz53tif7pyukfdophq
3838
- valory/abstract_round_abci:0.1.0:bafybeigjddhk7epta7xpnfvv426xedff5abh4xlkwi6cqgp4vkutgkvydm
39-
- valory/liquidity_trader_abci:0.1.0:bafybeidneasv2yf3uaujlvtnj7sphkc3bnlfzb4dmhxhivnarpavsqorle
40-
- valory/optimus_abci:0.1.0:bafybeicilmohuxn7bwzlvcdg6owii64vzyscqalswsdnxpngbqoxvbkjsq
39+
- valory/liquidity_trader_abci:0.1.0:bafybeia6vi5ojpzuziev63nyubllrccvkr6kiav73khdx7lf7npwx6pt2m
40+
- valory/optimus_abci:0.1.0:bafybeiffnvbgab3rkaik4t7p3q32nrgilhpgetkioqj76f7d3rhsopbhgi
4141
- valory/registration_abci:0.1.0:bafybeiagi6e2h7kochmlemy5c5yk6hwn37tfxiqvk2en74jhowsdwlmrny
4242
- valory/reset_pause_abci:0.1.0:bafybeiezfedmmseox3ce5aucxsiszdmvskrwwbtpb2a3vw3sbmc5jt7nri
4343
- valory/termination_abci:0.1.0:bafybeiea67epwwgngp7b3wavs6hpkaxv6etyaps6g6325bchfnf354mibq
4444
- valory/transaction_settlement_abci:0.1.0:bafybeifmgmwdkx4esemxjacjwzqkqymkuklb5nehkwqkx7v335fllgswcq
4545
customs:
4646
- valory/merkl_pools_search:0.1.0:bafybeihg3shkrvx7yzrqenjow23ebcl5xskrzrqkj47er2z47xhhs2z6ma
4747
- valory/max_apr_selection:0.1.0:bafybeihk4ehqcwlwlqdl2ifkyz2hfwfs232fs3n5rt64wfrobjt5ot2woy
48-
- valory/balancer_pools_search:0.1.0:bafybeihzodbkd4vatcphzu4672x5nitymhchbecvew7rpbu3hteh5rgyai
48+
- valory/balancer_pools_search:0.1.0:bafybeid7tyebp2cmnkclqysnhjufppf7fggbpl7sigqinuigtxaj74fc3m
4949
- valory/uniswap_pools_search:0.1.0:bafybeib7ibbjnhycdzyd3ind2no3sn77wxnlde3etxzh65lycj6obodq2e
50-
- valory/asset_lending:0.1.0:bafybeiejhhvualyp7xokskpyc3ki2k3u7v42qwe3hva36pgph3d2qwn6zu
50+
- valory/asset_lending:0.1.0:bafybeigjrvck43iqoh427ziph7ov4m2kg332prbwybxkepjfv536yczxky
5151
default_ledger: ethereum
5252
required_ledgers:
5353
- ethereum
@@ -259,7 +259,7 @@ models:
259259
balancer_graphql_endpoints: ${str:{"optimism":"https://api.studio.thegraph.com/query/75376/balancer-optimism-v2/version/latest","base":"https://api.studio.thegraph.com/query/24660/balancer-base-v2/version/latest","mode":"https://api.studio.thegraph.com/query/75376/balancer-mode-v2/version/latest"}}
260260
target_investment_chains: ${list:["mode"]}
261261
staking_chain: ${str:""}
262-
file_hash_to_strategies: ${str:{"bafybeibywngxfy5e2crtkvgfvad2ciepg3qk3h54eg3vbjoxwvf2j55wzq":"merkl_pools_search","bafybeihk4ehqcwlwlqdl2ifkyz2hfwfs232fs3n5rt64wfrobjt5ot2woy":"max_apr_selection","bafybeigacfwml5k4lhar33frqgxssgqqoqckhmabhcpnrtrhwzi7mte2b4":"balancer_pools_search","bafybeib6po22vum6uixlft2zqpxgsekjeccbzs75ii5xbi4rl5ggwotsky":"uniswap_pools_search","bafybeihmzaaidghrdvre7zkbdds3xc3jk4xqlas7kw5abb6hympzsodzp4":"asset_lending"}}
262+
file_hash_to_strategies: ${str:{"bafybeibywngxfy5e2crtkvgfvad2ciepg3qk3h54eg3vbjoxwvf2j55wzq":"merkl_pools_search","bafybeihk4ehqcwlwlqdl2ifkyz2hfwfs232fs3n5rt64wfrobjt5ot2woy":"max_apr_selection","bafybeid7tyebp2cmnkclqysnhjufppf7fggbpl7sigqinuigtxaj74fc3m":"balancer_pools_search","bafybeib6po22vum6uixlft2zqpxgsekjeccbzs75ii5xbi4rl5ggwotsky":"uniswap_pools_search","bafybeigjrvck43iqoh427ziph7ov4m2kg332prbwybxkepjfv536yczxky":"asset_lending"}}
263263
strategies_kwargs: ${str:{"merkl_pools_search":{"balancer_graphql_endpoints":{"optimism":"https://api.studio.thegraph.com/query/75376/balancer-optimism-v2/version/latest","base":"https://api.studio.thegraph.com/query/24660/balancer-base-v2/version/latest","mode":"https://api.studio.thegraph.com/query/75376/balancer-mode-v2/version/latest"},"merkl_fetch_campaign_args":{"url":"https://api.merkl.xyz/v3/campaigns","creator":"","live":"false"}},"uniswap_pools_search":{"graphql_endpoints":{"optimism":"https://gateway.thegraph.com/api/575c6d9779719bc1ced85444c98441be/subgraphs/id/7SVwgBfXoWmiK6x1NF1VEo1szkeWLniqWN1oYsX3UMb5","base":"https://gateway.thegraph.com/api/575c6d9779719bc1ced85444c98441be/subgraphs/id/GqzP4Xaehti8KSfQmv3ZctFSjnSUYZ4En5NRsiTbvZpz"}},"balancer_pools_search":{"graphql_endpoint":"https://api-v3.balancer.fi/"},"asset_lending":{"endpoint":"https://us-central1-stu-dashboard-a0ba2.cloudfunctions.net/v2Aggregators","lending_asset":"0x4200000000000000000000000000000000000006"}}}
264264
selected_strategies: ${list:["asset_lending","balancer_pools_search"]}
265265
selected_protocols: ${list:["BALANCER","UNISWAP_V3","STURDY"]}

packages/valory/customs/asset_lending/asset_lending.py

+68-26
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import warnings
22

3-
43
warnings.filterwarnings("ignore")
54

65
import json
@@ -15,7 +14,6 @@
1514
from pycoingecko import CoinGeckoAPI
1615
from web3 import Web3
1716

18-
1917
# Configure _logger
2018
_logger = setup_logger(__name__)
2119

@@ -46,6 +44,8 @@
4644
_aggregators_cache = None
4745
_historical_data_cache = None
4846

47+
# Error list
48+
errors = []
4949

5050
def get_coin_list():
5151
global _coin_list_cache
@@ -56,7 +56,7 @@ def get_coin_list():
5656
response.raise_for_status()
5757
_coin_list_cache = response.json()
5858
except requests.RequestException as e:
59-
_logger.error(f"Failed to fetch coin list: {e}")
59+
errors.append(f"Failed to fetch coin list: {e}")
6060
_coin_list_cache = []
6161
return _coin_list_cache
6262

@@ -72,7 +72,7 @@ def fetch_token_id(symbol):
7272
if coin["symbol"].lower() == symbol:
7373
return coin["id"]
7474

75-
_logger.error(f"Failed to fetch id for coin with symbol: {symbol}")
75+
errors.append(f"Failed to fetch id for coin with symbol: {symbol}")
7676
return None
7777

7878

@@ -86,7 +86,8 @@ def fetch_historical_data(limit: int = 720):
8686
url = f"https://us-central1-stu-dashboard-a0ba2.cloudfunctions.net/getV2AggregatorHistoricalData?last_time={one_month_ago_ms}&limit={limit}"
8787
response = requests.get(url)
8888
if response.status_code != 200:
89-
raise Exception("Failed to fetch historical data from STURDY API.")
89+
errors.append("Failed to fetch historical data from STURDY API.")
90+
return None
9091
_historical_data_cache = response.json()
9192
return _historical_data_cache
9293

@@ -166,12 +167,12 @@ def fetch_aggregators() -> List[Dict[str, Any]]:
166167
response.raise_for_status()
167168
result = response.json()
168169
if "errors" in result:
169-
_logger.error(f"REST API Errors: {result['errors']}")
170+
errors.append(f"REST API Errors: {result['errors']}")
170171
_aggregators_cache = []
171172
else:
172173
_aggregators_cache = result
173174
except requests.RequestException as e:
174-
_logger.error(f"REST API request failed: {e}")
175+
errors.append(f"REST API request failed: {e}")
175176
_aggregators_cache = []
176177
return _aggregators_cache
177178

@@ -200,7 +201,7 @@ def filter_aggregators(
200201
filtered_aggregators.append(aggregator)
201202

202203
if not filtered_aggregators:
203-
_logger.error("No suitable aggregator found.")
204+
errors.append("No suitable aggregator found.")
204205
return []
205206

206207
# If very few aggregators, return them directly
@@ -226,7 +227,7 @@ def filter_aggregators(
226227
scored_aggregators.append(aggregator)
227228

228229
if not scored_aggregators:
229-
_logger.error("No suitable aggregator found after scoring.")
230+
errors.append("No suitable aggregator found after scoring.")
230231
return []
231232

232233
score_threshold = np.percentile(
@@ -239,7 +240,7 @@ def filter_aggregators(
239240
filtered_scored_aggregators.sort(key=lambda x: x["score"], reverse=True)
240241

241242
if not filtered_scored_aggregators:
242-
_logger.error("No suitable aggregator found after score threshold.")
243+
errors.append("No suitable aggregator found after score threshold.")
243244
return []
244245

245246
# Limit to top 10 scored pools if more than 10
@@ -256,12 +257,16 @@ def calculate_il_risk_score_for_lending(
256257
time_period: int = 90,
257258
) -> float:
258259
if not asset_token_1 or not asset_token_2:
259-
_logger.error(
260+
errors.append(
260261
"Tokens are required. Cannot calculate IL risk score without asset tokens"
261262
)
262-
return float("nan")
263+
return None
263264

264-
cg = CoinGeckoAPI(demo_api_key=coingecko_api_key)
265+
is_pro = is_pro_api_key(coingecko_api_key)
266+
if is_pro:
267+
cg = CoinGeckoAPI(api_key=coingecko_api_key)
268+
else:
269+
cg = CoinGeckoAPI(demo_api_key=coingecko_api_key)
265270
to_timestamp = int(datetime.now().timestamp())
266271
from_timestamp = int((datetime.now() - timedelta(days=time_period)).timestamp())
267272

@@ -279,15 +284,15 @@ def calculate_il_risk_score_for_lending(
279284
to_timestamp=to_timestamp,
280285
)
281286
except Exception as e:
282-
_logger.error(f"Error fetching price data: {e}")
283-
return float("nan")
284-
287+
errors.append(f"Error fetching price data: Incorrect Coingecko API Key")
288+
return None
289+
285290
prices_1_data = np.array([x[1] for x in prices_1["prices"]])
286291
prices_2_data = np.array([x[1] for x in prices_2["prices"]])
287292

288293
min_length = min(len(prices_1_data), len(prices_2_data))
289294
if min_length == 0:
290-
return float("nan")
295+
return None
291296

292297
prices_1_data = prices_1_data[:min_length]
293298
prices_2_data = prices_2_data[:min_length]
@@ -319,7 +324,7 @@ def get_token_id(symbol):
319324

320325
token_0_id = get_token_id(token0_symbol)
321326
if not token_0_id:
322-
return float("nan")
327+
return None
323328

324329
for silo in silos:
325330
token_1_symbol = silo["collateral"].lower()
@@ -329,12 +334,15 @@ def get_token_id(symbol):
329334
il_risk_score = calculate_il_risk_score_for_lending(
330335
token_0_id, token_1_id, coingecko_api_key
331336
)
337+
if not il_risk_score:
338+
return None
339+
332340
il_risk_scores.append(il_risk_score)
333341
else:
334-
_logger.error(f"Failed to fetch token IDs for silo: {silo['collateral']}")
342+
errors.append(f"Failed to fetch token IDs for silo: {silo['collateral']}")
335343

336344
if not il_risk_scores:
337-
return float("nan")
345+
return None
338346

339347
return sum(il_risk_scores) / len(il_risk_scores)
340348

@@ -355,6 +363,7 @@ def analyze_vault_liquidity(aggregator):
355363
break
356364

357365
if not tvl or not total_assets:
366+
errors.append("Could not retrieve depth score and maximum position size.")
358367
return float("nan"), float("nan")
359368

360369
depth_score = (
@@ -389,15 +398,19 @@ def get_best_opportunities(
389398
) -> List[Dict[str, Any]]:
390399
data = fetch_aggregators()
391400
if not data:
392-
return []
401+
errors.append("Failed to fetch aggregators.")
402+
return {"error": errors}
393403

394404
filtered_aggregators = filter_aggregators(
395405
chains, data, lending_asset, current_positions
396406
)
397407
if not filtered_aggregators:
398-
return []
408+
errors.append("No suitable aggregators found.")
409+
return {"error": errors}
399410

400411
historical_data = fetch_historical_data()
412+
if historical_data is None:
413+
return {"error": errors}
401414

402415
for aggregator in filtered_aggregators:
403416
silos = aggregator.get("whitelistedSilos", [])
@@ -427,6 +440,9 @@ def calculate_metrics(
427440
coingecko_api_key,
428441
)
429442
historical_data = fetch_historical_data()
443+
if historical_data is None:
444+
return {"error": errors}
445+
430446
sharpe_ratio = get_sharpe_ratio_for_address(
431447
historical_data, position["pool_address"]
432448
)
@@ -439,10 +455,31 @@ def calculate_metrics(
439455
}
440456

441457

458+
def is_pro_api_key(coingecko_api_key: str) -> bool:
459+
"""
460+
Check if the provided CoinGecko API key is a pro key.
461+
"""
462+
# Try using the key as a pro API key
463+
cg_pro = CoinGeckoAPI(api_key=coingecko_api_key)
464+
try:
465+
response = cg_pro.get_coin_market_chart_range_by_id(
466+
id="bitcoin",
467+
vs_currency="usd",
468+
from_timestamp=0,
469+
to_timestamp=0
470+
)
471+
if response:
472+
return True
473+
except Exception:
474+
return False
475+
476+
return False
477+
442478
def run(*_args, **kwargs) -> Any:
443479
missing = check_missing_fields(kwargs)
444480
if missing:
445-
return {"error": f"Required kwargs {missing} were not provided."}
481+
errors.append(f"Required kwargs {missing} were not provided.")
482+
return {"error": errors}
446483

447484
required_fields = list(REQUIRED_FIELDS)
448485
get_metrics = kwargs.get("get_metrics", False)
@@ -452,9 +489,14 @@ def run(*_args, **kwargs) -> Any:
452489
kwargs = remove_irrelevant_fields(kwargs, required_fields)
453490

454491
if get_metrics:
455-
return calculate_metrics(**kwargs)
492+
metrics = calculate_metrics(**kwargs)
493+
if metrics is None:
494+
errors.append("Failed to calculate metrics.")
495+
return {"error": errors} if errors else metrics
456496
else:
457497
result = get_best_opportunities(**kwargs)
498+
if isinstance(result, dict) and "error" in result:
499+
errors.append(result["error"])
458500
if not result:
459-
return {"error": "No suitable aggregators found"}
460-
return result
501+
errors.append("No suitable aggregators found")
502+
return {"error": errors} if errors else {"result": result}

packages/valory/customs/asset_lending/component.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ license: Apache-2.0
88
aea_version: '>=1.0.0, <2.0.0'
99
fingerprint:
1010
__init__.py: bafybeiguqxojq5hkgi55jqdl5p3rvz62jwxxw6ygorkym7ol3ps5qhh7rq
11-
asset_lending.py: bafybeibwsqmpfni353zyajddk6bhevmaq534dlhmcqli6hoqyivqvupibu
11+
asset_lending.py: bafybeib3dd2feyhdgldaueo2yyw2ex442pslm7vg7hdue52sisyvgj6are
1212
fingerprint_ignore_patterns: []
1313
entry_point: asset_lending.py
1414
callable: run

0 commit comments

Comments
 (0)