diff --git a/lib/pt_trading/results.py b/lib/pt_trading/results.py index 8285f7f..3d4e229 100644 --- a/lib/pt_trading/results.py +++ b/lib/pt_trading/results.py @@ -474,8 +474,11 @@ class BacktestResult: """Clear all trades (used when processing new files).""" self.trades.clear() - def collect_single_day_results(self, result: pd.DataFrame) -> None: + def collect_single_day_results(self, pairs_trades: List[pd.DataFrame]) -> None: """Collect and process single day trading results.""" + result = pd.concat(pairs_trades, ignore_index=True) + result["time"] = pd.to_datetime(result["time"]) + result = result.set_index("time").sort_index() print("\n -------------- Suggested Trades ") print(result) @@ -695,7 +698,7 @@ class BacktestResult: print("-" * 100) - total_value += pos["total_current_value"] + total_value += pos["total_current_value"] print(f"{'TOTAL OUTSTANDING VALUE':<80} ${total_value:<12.2f}") @@ -742,8 +745,8 @@ class BacktestResult: shares_b = funding_per_position / open_px_b # Calculate current position values (shares * current price) - current_value_a = shares_a * last_px_a - current_value_b = shares_b * last_px_b + current_value_a = shares_a * last_px_a * (-1 if open_side_a == "SELL" else 1) + current_value_b = shares_b * last_px_b * (-1 if open_side_b == "SELL" else 1) total_current_value = current_value_a + current_value_b # Get disequilibrium information diff --git a/lib/pt_trading/trading_pair.py b/lib/pt_trading/trading_pair.py index c355d7a..30626ff 100644 --- a/lib/pt_trading/trading_pair.py +++ b/lib/pt_trading/trading_pair.py @@ -263,4 +263,8 @@ class TradingPair: return self.predicted_df_ def __repr__(self) -> str: + return self.name() + + def name(self) -> str: return f"{self.symbol_a_} & {self.symbol_b_}" + # return f"{self.symbol_a_} & {self.symbol_b_}" diff --git a/research/notebooks/pt_sliding.ipynb b/research/notebooks/pt_sliding.ipynb index b33deba..0143074 100644 --- a/research/notebooks/pt_sliding.ipynb +++ b/research/notebooks/pt_sliding.ipynb @@ -43,7 +43,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -59,6 +59,9 @@ "global PT_BT_CONFIG\n", "global DATA_FILE\n", "global FIT_METHOD_TYPE\n", + "global pair\n", + "global pair_trades\n", + "global bt_result\n", "\n", "FIT_METHOD_TYPE = \"SlidingFit\"\n", "\n", @@ -89,7 +92,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -128,7 +131,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -208,7 +211,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -295,7 +298,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -353,7 +356,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -398,7 +401,7 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -490,7 +493,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -560,7 +563,7 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -1139,16 +1142,16 @@ } }, "source": [ - "## Summary and Analysis\n" + "## Summary\n" ] }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ - "def summary_and_analysis() -> None:\n", + "def summary() -> None:\n", " print(\"=\" * 80)\n", " print(\"PAIRS TRADING BACKTEST SUMMARY\")\n", " print(\"=\" * 80)\n", @@ -1214,16 +1217,23 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "def performance_results() -> None:\n", - " from datetime import datetime\n", + " global pair_trades\n", + " global bt_result\n", + " global SYMBOL_A\n", + " global SYMBOL_B\n", + " global FIT_METHOD_TYPE\n", + " global PT_BT_CONFIG\n", + "\n", + " from pt_trading.results import BacktestResult\n", "\n", " if pair_trades is not None and len(pair_trades) > 0:\n", " # Print detailed results using BacktestResult methods\n", - " bt_result.print_single_day_results()\n", + " # bt_result.print_single_day_results()\n", " \n", " # Print trading signal details\n", " print(f\"\\nDetailed Trading Signals:\")\n", @@ -1243,11 +1253,24 @@ " if len(pair_trades) > 10:\n", " print(f\"... and {len(pair_trades)-10} more trading signals\")\n", " \n", - " # Print outstanding positions\n", - " bt_result.print_outstanding_positions()\n", - " \n", - " # Print grand totals\n", - " bt_result.print_grand_totals()\n", + " bt_result.collect_single_day_results([pair_trades])\n", + "\n", + " # bt_result.print_grand_totals()\n", + " # bt_result.print_outstanding_positions() \n", + "\n", + " all_results: Dict[str, Dict[str, Any]] = {}\n", + " all_results[f\"{TRADING_DATE}-{pair.name()}\"] = {\n", + " \"trades\": bt_result.trades.copy(), \n", + " \"outstanding_positions\": bt_result.outstanding_positions.copy()\n", + " }\n", + "\n", + " if all_results:\n", + " aggregate_bt_results = BacktestResult(config=PT_BT_CONFIG)\n", + " aggregate_bt_results.calculate_returns(all_results)\n", + " aggregate_bt_results.print_grand_totals()\n", + " aggregate_bt_results.print_outstanding_positions()\n", + "\n", + "\n", " \n", " else:\n", " print(f\"\\nNo trading signals generated\")\n", @@ -1261,7 +1284,9 @@ " print(f\" Close threshold: {pt_bt_config['dis-equilibrium_close_trshld']}\")\n", " print(f\" Training window: {pt_bt_config['training_minutes']} minutes\")\n", " \n", - " print(\"\\n\" + \"=\"*80)\n" + " print(\"\\n\" + \"=\"*80)\n", + "\n", + "# performance_results()" ] }, { @@ -1273,7 +1298,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -1496,9 +1521,9 @@ "COIN & MSTR: *** Position is NOT CLOSED. ***\n", "COIN & MSTR: NO CLOSE SIGNAL FOUND - Position held until end of session\n", " Open: 2025-06-04 19:16:00 | Last: 2025-06-04 15:30:00\n", - " COIN: SELL 3.92 shares @ $255.00 -> $256.83 | Value: $1007.18\n", + " COIN: SELL 3.92 shares @ $255.00 -> $256.83 | Value: $-1007.18\n", " MSTR: BUY 2.62 shares @ $382.24 -> $383.12 | Value: $1002.30\n", - " Total Value: $2009.48\n", + " Total Value: $-4.87\n", " Disequilibrium: -1.8682 | Scaled: 1.5623\n", "***COIN & MSTR*** FINISHED ... 10\n", "Generated 10 trading signals\n", @@ -3991,9 +4016,9 @@ }, "text/html": [ "
\n", - "
\n", - "