Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions alpha/AutoRegression/autoregression.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from pathlib import Path

import numpy as np
import torch
from torch import nn
from torch.utils.data import Dataset, DataLoader
import numpy as np
from pathlib import Path
from torch.utils.data import DataLoader, Dataset


class AR(nn.Module):
def __init__(self, lag):
Expand Down
1 change: 1 addition & 0 deletions alpha/AutoRegression/data_processing.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import numpy as np
import pandas as pd


def load_data(data_path: str = "./binance/BTC_USDT-5m.feather",
start_date: str = "2021-01-01"):
df = pd.read_feather(data_path)
Expand Down
3 changes: 2 additions & 1 deletion alpha/AutoregressionAlpha.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import numpy as np
import torch
from pandas import DataFrame

from alpha.AutoRegression.autoregression import build_train, trained_ar_model
from alpha.interface import IAlpha
from alpha.AutoRegression.autoregression import trained_ar_model, build_train

AR_MODEL_PATH = "./ar_model.pth"
AR_LAG = 90
Expand Down
2 changes: 1 addition & 1 deletion alpha/BollingerAlpha.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
"""

import talib.abstract as ta
from freqtrade.strategy.parameters import IntParameter

from alpha.interface import IAlpha
from freqtrade.strategy.parameters import IntParameter


class BollingerAlpha(IAlpha):
Expand Down
6 changes: 4 additions & 2 deletions alpha/EventLstmAlpha.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import torch
import numpy as np
import torch
import torch.nn as nn
from pandas import DataFrame

from alpha.interface import IAlpha
import torch.nn as nn


class EventLstmModel(nn.Module):
def __init__(self):
Expand Down
2 changes: 1 addition & 1 deletion alpha/MacdAlpha.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
"""

import talib.abstract as ta
from freqtrade.strategy.parameters import IntParameter

from alpha.interface import IAlpha
from freqtrade.strategy.parameters import IntParameter


class MacdAlpha(IAlpha):
Expand Down
2 changes: 1 addition & 1 deletion alpha/RsiAlpha.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
"""

import talib.abstract as ta
from freqtrade.strategy.parameters import IntParameter

from alpha.interface import IAlpha
from freqtrade.strategy.parameters import IntParameter


class RsiAlpha(IAlpha):
Expand Down
3 changes: 2 additions & 1 deletion alpha/SimpleEmaFactors.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import talib.abstract as ta
from freqtrade.strategy.parameters import IntParameter

from alpha.interface import IAlpha
from freqtrade.strategy.parameters import IntParameter


class EmaAlpha(IAlpha):
def __init__(self, dataframe, metadata):
Expand Down
2 changes: 2 additions & 0 deletions alpha/interface.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from abc import ABC, abstractmethod

from pandas import DataFrame


class IAlpha(ABC):
def __init__(self, dataframe: DataFrame, metadata: dict = None):
self.dataframe=dataframe
Expand Down
17 changes: 9 additions & 8 deletions benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@
python benchmark.py --export report.json # also write JSON results
"""

import argparse
import json
import os
import sys
import json
import time
import traceback
import argparse
from concurrent.futures import ProcessPoolExecutor, as_completed
from datetime import datetime
from typing import Any, Dict, List, Optional, Tuple
Expand All @@ -40,8 +39,8 @@
# ---------------------------------------------------------------------------
try:
from freqtrade.commands.optimize_commands import setup_optimize_configuration
from freqtrade.optimize.backtesting import Backtesting
from freqtrade.enums import RunMode
from freqtrade.optimize.backtesting import Backtesting
FREQTRADE_AVAILABLE = True
except ImportError as e:
FREQTRADE_AVAILABLE = False
Expand Down Expand Up @@ -481,10 +480,11 @@ def run_alpha_smoke_test() -> Dict[str, Any]:
t0 = time.time()
try:
import pandas as pd
from alpha.SimpleEmaFactors import EmaAlpha
from alpha.RsiAlpha import RsiAlpha
from alpha.MacdAlpha import MacdAlpha

from alpha.BollingerAlpha import BollingerAlpha
from alpha.MacdAlpha import MacdAlpha
from alpha.RsiAlpha import RsiAlpha
from alpha.SimpleEmaFactors import EmaAlpha

# Load one pair's data
filepath = os.path.join(DATA_DIR, "BTC_USDT-1d.feather")
Expand Down Expand Up @@ -564,9 +564,10 @@ def run_data_integrity_check() -> Dict[str, Any]:
}
t0 = time.time()
try:
import pandas as pd
from pathlib import Path

import pandas as pd

data_path = Path(DATA_DIR)
feather_files = sorted(data_path.glob("*.feather"))
total = len(feather_files)
Expand Down
5 changes: 2 additions & 3 deletions benchmark_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,9 @@
import os
import sys
import time
import traceback
from concurrent.futures import ProcessPoolExecutor, as_completed
from datetime import datetime
from typing import Any, Dict, List, Optional, Tuple
from typing import Any, Dict, List, Tuple

# ---------------------------------------------------------------------------
# Ensure project root is on sys.path
Expand Down Expand Up @@ -433,8 +432,8 @@ def _run_single_backtest(
) -> Dict[str, Any]:
"""Run a single freqtrade backtest programmatically and return results."""
from freqtrade.commands.optimize_commands import setup_optimize_configuration
from freqtrade.optimize.backtesting import Backtesting
from freqtrade.enums import RunMode
from freqtrade.optimize.backtesting import Backtesting

config_path = os.path.join(PROJECT_ROOT, "user_data", "config.json")

Expand Down
20 changes: 10 additions & 10 deletions examples/pipeline_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,22 @@

import sys
from pathlib import Path
import pandas as pd

import numpy as np
import pandas as pd

# Add project root to path
PROJECT_ROOT = Path(__file__).parent.parent
sys.path.insert(0, str(PROJECT_ROOT))

from pipeline.config import PipelineConfig, PresetConfigs
from pipeline.orchestrator import PortfolioPipeline, run_pipeline
from pipeline.integrations import (
FreqtradeIntegration,
BatchPipelineRunner,
PresetPipelineRunner,
FreqtradeIntegration,
PipelineComparator,
PresetPipelineRunner,
)

from pipeline.orchestrator import run_pipeline

# ============================================================================
# HELPER: Generate synthetic test data
Expand Down Expand Up @@ -99,13 +99,13 @@ def example_2_custom_config():

from pipeline.config import (
AlphaConfig,
StrategyConfig,
PortfolioConfig,
AlphaType,
BacktestConfig,
DataConfig,
AlphaType,
StrategyType,
PortfolioAlgorithm,
PortfolioConfig,
StrategyConfig,
StrategyType,
)

# Build configuration programmatically
Expand Down Expand Up @@ -212,7 +212,7 @@ def example_4_compare_pipelines():

# Print summary
summary = runner.get_summary()
print(f"\nBatch Summary:")
print("\nBatch Summary:")
print(f" Total runs: {summary['total_runs']}")
print(f" Successful: {summary['successful']}")
print(f" Failed: {summary['failed']}")
Expand Down
5 changes: 3 additions & 2 deletions fix_utc_imports.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
import os
import re


def fix_utc_imports(filepath):
"""Fix UTC imports in a Python file for Python 3.10 compatibility."""
with open(filepath, 'r', encoding='utf-8') as f:
with open(filepath, encoding='utf-8') as f:
content = f.read()

# Check if already fixed
Expand Down Expand Up @@ -92,7 +93,7 @@ def fix_utc_imports(filepath):
if file.endswith('.py'):
filepath = os.path.join(root, file)
try:
with open(filepath, 'r', encoding='utf-8') as f:
with open(filepath, encoding='utf-8') as f:
content = f.read()
if 'from datetime import' in content and 'UTC' in content:
attempted += 1
Expand Down
6 changes: 3 additions & 3 deletions pipeline/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@

import json
import os
from dataclasses import dataclass, field, asdict
from dataclasses import asdict, dataclass, field
from enum import Enum
from pathlib import Path
from typing import Any, Dict, List, Optional
from enum import Enum


class AlphaType(str, Enum):
Expand Down Expand Up @@ -210,7 +210,7 @@ def from_yaml(cls, filepath: str | Path) -> PipelineConfig:
raise ImportError("PyYAML required for YAML config support. "
"Install with: pip install PyYAML")

with open(filepath, 'r') as f:
with open(filepath) as f:
data = yaml.safe_load(f)
return cls.from_dict(data)

Expand Down
5 changes: 3 additions & 2 deletions pipeline/integrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@
from __future__ import annotations

import json
import logging
import pickle
from pathlib import Path
from typing import Dict, List, Any, Optional
from typing import Any, Dict, List

import pandas as pd
import logging

logger = logging.getLogger(__name__)

Expand Down
24 changes: 12 additions & 12 deletions pipeline/orchestrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,34 @@

from __future__ import annotations

import logging
import os
import sys
import time
import logging
from pathlib import Path
from typing import Dict, List, Optional, Tuple, Any
import pandas as pd
from typing import Dict, List

import numpy as np
import pandas as pd

# Ensure project root is on path
_PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if _PROJECT_ROOT not in sys.path:
sys.path.insert(0, _PROJECT_ROOT)

from pipeline.config import PipelineConfig, AlphaType, StrategyType
from pipeline.verification import PipelineVerification, ValidationResult
from pipeline.config import AlphaType, PipelineConfig, StrategyType
from pipeline.results import PipelineResult, StageOutput

from pipeline.verification import PipelineVerification
from portfolio.PortfolioManagement import (
load_pair_data,
align_close_prices,
ema_cross_signals,
backtest_portfolio,
blend_strategy_weights,
build_ema_position_series,
calculate_ons_weights,
equal_weight_allocation,
blend_strategy_weights,
backtest_portfolio,
compute_metrics,
ema_cross_signals,
equal_weight_allocation,
load_pair_data,
)

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -184,7 +184,7 @@ def run(self) -> PipelineResult:
data_summary=metrics
))

logger.info(f"\nBacktest Results:")
logger.info("\nBacktest Results:")
logger.info(f" Total return: {metrics['total_return_pct']:.2f}%")
logger.info(f" Annualized return: {metrics['annualised_return_pct']:.2f}%")
logger.info(f" Annualized Sharpe: {metrics['annualised_sharpe']:.4f}")
Expand Down
12 changes: 5 additions & 7 deletions pipeline/results.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@

import json
import logging
from dataclasses import dataclass, field, asdict
from dataclasses import asdict, dataclass, field
from pathlib import Path
from typing import Dict, List, Any, Optional
from datetime import datetime
import pandas as pd
import numpy as np
from typing import Any, Dict, List, Optional

import pandas as pd

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -204,7 +202,7 @@ def to_html_report(self) -> str:
"</head>",
"<body>",
"<div class='header'>",
f"<h1>PortfolioBench Pipeline Report</h1>",
"<h1>PortfolioBench Pipeline Report</h1>",
f"<p>Pipeline: {summary['pipeline_name']}</p>",
f"<p>Duration: {summary['duration_s']:.2f}s</p>",
"</div>",
Expand Down Expand Up @@ -325,7 +323,7 @@ def print_summary(self) -> None:
print(f" [~] Skipped: {stages['skipped']}")

if summary['metrics']:
print(f"\nMetrics:")
print("\nMetrics:")
for key, value in summary['metrics'].items():
if value is not None:
if isinstance(value, float):
Expand Down
Loading
Loading