From 02bc74b52fd5d0c89899d41b9f5164bc7bbf3c7a Mon Sep 17 00:00:00 2001 From: Jordan Bonilla Date: Wed, 8 Jan 2025 17:05:40 -0500 Subject: [PATCH] progress --- tests/vali_tests/test_perf_ledgers.py | 14 +++--- vali_objects/vali_dataclasses/perf_ledger.py | 47 ++++++++++++-------- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/tests/vali_tests/test_perf_ledgers.py b/tests/vali_tests/test_perf_ledgers.py index e281358b..e9a26020 100644 --- a/tests/vali_tests/test_perf_ledgers.py +++ b/tests/vali_tests/test_perf_ledgers.py @@ -6,7 +6,7 @@ from vali_objects.enums.order_type_enum import OrderType from vali_objects.position import Position from vali_objects.vali_dataclasses.order import Order -from vali_objects.vali_dataclasses.perf_ledger import PerfLedgerManager +from vali_objects.vali_dataclasses.perf_ledger import PerfLedgerManager, TP_ID_PORTFOLIO class TestPerfLedgers(TestBase): @@ -36,9 +36,13 @@ def test_basic(self, mock_unified_candle_fetcher): perf_ledger_manager = PerfLedgerManager(metagraph=None, running_unit_tests=True) hotkey_to_positions = {self.DEFAULT_MINER_HOTKEY: [self.default_open_position]} ans = perf_ledger_manager.generate_perf_ledgers_for_analysis(hotkey_to_positions) - for x in ans[self.DEFAULT_MINER_HOTKEY].cps: - last_update_formated = TimeUtil.millis_to_timestamp(x.last_update_ms) - print(x, last_update_formated) - print('max_perf_ledger_return:', ans[self.DEFAULT_MINER_HOTKEY].max_return) + for hk, dat in ans.items(): + for tp_id, pl in dat.items(): + print('-----------', tp_id, '-----------') + for idx, x in enumerate(pl.cps): + last_update_formatted = TimeUtil.millis_to_timestamp(x.last_update_ms) + if idx == 0 or idx == len(pl.cps) - 1: + print(x, last_update_formatted) + print(tp_id, 'max_perf_ledger_return:', pl.max_return) assert len(ans) == 1, ans diff --git a/vali_objects/vali_dataclasses/perf_ledger.py b/vali_objects/vali_dataclasses/perf_ledger.py index d561749a..5374b9f3 100644 --- a/vali_objects/vali_dataclasses/perf_ledger.py +++ b/vali_objects/vali_dataclasses/perf_ledger.py @@ -416,7 +416,7 @@ def __init__(self, metagraph, live_price_fetcher=None, running_unit_tests=False, self.hotkey_to_checkpointed_ledger = {} - def load_perf_ledgers_from_disk(self, read_as_pydantic=True) -> dict[str, PerfLedgerData]: + def load_perf_ledgers_from_disk(self, read_as_pydantic=True) -> dict[str, dict[str, PerfLedgerData]]: file_path = ValiBkpUtils.get_perf_ledgers_path(self.running_unit_tests) if not os.path.exists(file_path): return {} @@ -425,13 +425,13 @@ def load_perf_ledgers_from_disk(self, read_as_pydantic=True) -> dict[str, PerfLe data = json.load(file) perf_ledgers = {} - for key, ledger_data in data.items(): - if read_as_pydantic: - ledger_data['cps'] = [PerfCheckpoint(**cp) for cp in ledger_data['cps']] - perf_ledgers[key] = PerfLedger(**ledger_data) - else: - ledger_data['cps'] = [PerfCheckpointData(**cp) for cp in ledger_data['cps']] - perf_ledgers[key] = PerfLedgerData(**ledger_data) + for hk, ledger_data in data.items(): + perf_ledgers[hk] = {} + for key, ledger in ledger_data.items(): + if read_as_pydantic: + perf_ledgers[hk][key] = PerfLedger(**ledger) + else: + perf_ledgers[hk][key] = PerfLedgerData(**ledger) return perf_ledgers @@ -764,8 +764,12 @@ def condense_positions(self, tp_to_historical_positions: dict[str: Position]) -> tp_to_historical_positions_dense[tp_id] = dense_positions return tp_to_initial_return, tp_to_initial_spread_fee, tp_to_initial_carry_fee, tp_to_historical_positions_dense - def build_perf_ledger(self, perf_ledger_bundle: dict[str:PerfLedgerData], tp_to_historical_positions: dict[str: Position], start_time_ms, end_time_ms, miner_hotkey, realtime_position_to_pop) -> bool: + def build_perf_ledger(self, perf_ledger_bundle: dict[str:dict[str, PerfLedgerData]], tp_to_historical_positions: dict[str: Position], start_time_ms, end_time_ms, miner_hotkey, realtime_position_to_pop) -> bool: #print(f"Building perf ledger for {miner_hotkey} from {start_time_ms} to {end_time_ms} ({(end_time_ms - start_time_ms) // 1000} s)") + portfolio_pl = perf_ledger_bundle[TP_ID_PORTFOLIO] + if len(portfolio_pl.cps) == 0: + portfolio_pl.init_with_first_order(end_time_ms, point_in_time_dd=1.0, current_portfolio_value=1.0, + current_portfolio_fee_spread=1.0, current_portfolio_carry=1.0) # Init per-trade-pair perf ledgers tp_ids_to_build = [TP_ID_PORTFOLIO] @@ -780,8 +784,9 @@ def build_perf_ledger(self, perf_ledger_bundle: dict[str:PerfLedgerData], tp_to_ relevant_position = realtime_position_to_pop initialization_time_ms = relevant_position.open_ms perf_ledger_bundle[tp_id] = PerfLedgerData(initialization_time_ms=initialization_time_ms) + perf_ledger_bundle[tp_id].init_with_first_order(end_time_ms, point_in_time_dd=1.0, current_portfolio_value=1.0, + current_portfolio_fee_spread=1.0, current_portfolio_carry=1.0) - portfolio_pl = perf_ledger_bundle[TP_ID_PORTFOLIO] if portfolio_pl.initialization_time_ms == end_time_ms: return False # Can only build perf ledger between orders or after all orders have passed. @@ -1037,12 +1042,16 @@ def get_positions_perf_ledger(self, testing_one_hotkey=None): return hotkey_to_positions, hotkeys_with_no_positions - def generate_perf_ledgers_for_analysis(self, hotkey_to_positions: dict[str, List[Position]], t_ms: int = None) -> dict[str, PerfLedger]: + def generate_perf_ledgers_for_analysis(self, hotkey_to_positions: dict[str, List[Position]], t_ms: int = None) -> dict[str, dict[str, PerfLedger]]: if t_ms is None: t_ms = TimeUtil.now_in_millis() # Time to build the perf ledgers up to. Goes back 30 days from this time. existing_perf_ledgers = {} - ans_data = self.update_all_perf_ledgers(hotkey_to_positions, existing_perf_ledgers, t_ms, return_dict=True) - ans_pydantic = {k: PerfLedger.from_data(v) for k, v in ans_data.items()} + dat = self.update_all_perf_ledgers(hotkey_to_positions, existing_perf_ledgers, t_ms, return_dict=True) + ans_pydantic = {} + for k, v in dat.items(): + ans_pydantic[k] = {} + for tp_id, pl in v.items(): + ans_pydantic[k][tp_id] = PerfLedger.from_data(pl) return ans_pydantic def update(self, testing_one_hotkey=None, regenerate_all_ledgers=False): @@ -1167,12 +1176,14 @@ def sort_key(x): print(' total loss product', pl.get_product_of_loss()) print(' total product', pl.get_total_product()) - def save_perf_ledgers_to_disk(self, perf_ledgers: dict[str, PerfLedgerData] | dict[str, dict], raw_json=False): + def save_perf_ledgers_to_disk(self, perf_ledgers: dict[str, dict[str, PerfLedgerData]] | dict[str, dict], raw_json=False): # Convert to PerfLedger (pydantic validation) - if raw_json: - pydantic_perf_ledgers = {key: PerfLedger.from_dict(value) for key, value in perf_ledgers.items()} - else: - pydantic_perf_ledgers = {key: PerfLedger.from_data(value) for key, value in perf_ledgers.items()} + pydantic_perf_ledgers = {} + for hk, dat in perf_ledgers.items(): + pydantic_perf_ledgers[hk] = {} + for tp_id, pl in dat.items(): + pydantic_perf_ledgers[hk][tp_id] = PerfLedger.from_dict(pl) if raw_json else PerfLedger.from_data(pl) + file_path = ValiBkpUtils.get_perf_ledgers_path(self.running_unit_tests) ValiBkpUtils.write_to_dir(file_path, pydantic_perf_ledgers)