| Overall Statistics |
|
Total Orders 96 Average Win 0.03% Average Loss -0.06% Compounding Annual Return 9.287% Drawdown 18.400% Expectancy -0.253 Start Equity 100000 End Equity 109304.95 Net Profit 9.305% Sharpe Ratio 0.484 Sortino Ratio 0.449 Probabilistic Sharpe Ratio 28.112% Loss Rate 47% Win Rate 53% Profit-Loss Ratio 0.42 Alpha -0.013 Beta 0.501 Annual Standard Deviation 0.139 Annual Variance 0.019 Information Ratio -0.677 Tracking Error 0.139 Treynor Ratio 0.135 Total Fees $96.00 Estimated Strategy Capacity $140000000.00 Lowest Capacity Asset SPY R735QTJ8XC9X Portfolio Turnover 0.27% |
from AlgorithmImports import *
class TwoTimeframesSameAsset(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2020, 1, 1)
self.SetEndDate(2021, 1, 1)
self.SetCash(100000)
self.spy = self.AddEquity("SPY", Resolution.Hour)
self.spy.SetDataNormalizationMode(DataNormalizationMode.Raw)
self.SetUniverseSelection(ManualUniverseSelectionModel(["SPY"]))
self.SetAlpha(CompositeAlphaModel(
HourlyStrategy(),
DailyStrategy()
))
self.SetPortfolioConstruction(CustomPortfolioConstructionModel())
self.SetExecution(ImmediateExecutionModel())
self.SetRiskManagement(NullRiskManagementModel())
def OnData(self, data):
self.Log(f"OnData called at {self.Time}: Data type: {data.GetType().Name}")
class HourlyStrategy(AlphaModel):
def __init__(self):
self.last_hour = None
self.Name = "HourlyStrategy"
def Update(self, algorithm: QCAlgorithm, data: Slice) -> List[Insight]:
if not data.ContainsKey("SPY"):
return []
current_hour = algorithm.Time.hour
if self.last_hour == current_hour:
return []
self.last_hour = current_hour
spy_data = data["SPY"]
if spy_data is None or spy_data.Price == 0:
return []
price = spy_data.Price
insight = Insight.Price("SPY", timedelta(hours=1), InsightDirection.Up if current_hour % 2 == 0 else InsightDirection.Down, sourceModel=self.Name)
algorithm.Log(f"Hourly Strategy: Generated {'Up' if current_hour % 2 == 0 else 'Down'} insight at {algorithm.Time}. Price: {price}")
return [insight]
class DailyStrategy(AlphaModel):
def __init__(self):
self.last_date = None
self.Name = "DailyStrategy"
def Update(self, algorithm: QCAlgorithm, data: Slice) -> List[Insight]:
if not data.ContainsKey("SPY"):
return []
current_date = algorithm.Time.date()
if self.last_date == current_date:
return []
self.last_date = current_date
spy_data = data["SPY"]
if spy_data is None or spy_data.Price == 0:
return []
price = spy_data.Price
insight = Insight.Price("SPY", timedelta(days=1), InsightDirection.Up if current_date.day % 2 == 0 else InsightDirection.Down, sourceModel=self.Name)
algorithm.Log(f"Daily Strategy: Generated {'Up' if current_date.day % 2 == 0 else 'Down'} insight at {algorithm.Time}. Price: {price}")
return [insight]
class CustomPortfolioConstructionModel(PortfolioConstructionModel):
def __init__(self):
self.hourly_allocation = 50000
self.daily_allocation = 50000
self.last_rebalance = datetime.min
self.rebalance_time = timedelta(days=1) # Rebalance daily
def CreateTargets(self, algorithm, insights):
if len(insights) == 0:
return []
current_time = algorithm.Time
if (current_time - self.last_rebalance) < self.rebalance_time:
return []
self.last_rebalance = current_time
# Update allocations based on current portfolio value
total_portfolio_value = max(0, algorithm.Portfolio.TotalPortfolioValue)
if self.hourly_allocation + self.daily_allocation > 0:
hourly_value = self.hourly_allocation / (self.hourly_allocation + self.daily_allocation) * total_portfolio_value
daily_value = self.daily_allocation / (self.hourly_allocation + self.daily_allocation) * total_portfolio_value
else:
hourly_value = daily_value = total_portfolio_value / 2
self.hourly_allocation = hourly_value
self.daily_allocation = daily_value
hourly_insights = [x for x in insights if x.SourceModel == "HourlyStrategy"]
daily_insights = [x for x in insights if x.SourceModel == "DailyStrategy"]
targets = []
spy_price = algorithm.Securities["SPY"].Price
if spy_price > 0:
if hourly_insights and len(hourly_insights) > 0:
hourly_direction = hourly_insights[0].Direction
hourly_target = PortfolioTarget("SPY", self.hourly_allocation / spy_price * (1 if hourly_direction == InsightDirection.Up else -1))
targets.append(hourly_target)
if daily_insights and len(daily_insights) > 0:
daily_direction = daily_insights[0].Direction
daily_target = PortfolioTarget("SPY", self.daily_allocation / spy_price * (1 if daily_direction == InsightDirection.Up else -1))
targets.append(daily_target)
algorithm.Log(f"Rebalancing at {current_time}. Hourly allocation: ${self.hourly_allocation:.2f}, Daily allocation: ${self.daily_allocation:.2f}")
return targets
def OnSecuritiesChanged(self, algorithm, changes):
pass