| Overall Statistics |
|
Total Orders 957 Average Win 0.75% Average Loss -0.68% Compounding Annual Return 10.139% Drawdown 25.000% Expectancy 0.122 Start Equity 1000000 End Equity 1434577.72 Net Profit 43.458% Sharpe Ratio 0.331 Sortino Ratio 0.286 Probabilistic Sharpe Ratio 12.571% Loss Rate 46% Win Rate 54% Profit-Loss Ratio 1.09 Alpha 0.017 Beta 0.488 Annual Standard Deviation 0.157 Annual Variance 0.024 Information Ratio -0.129 Tracking Error 0.158 Treynor Ratio 0.106 Total Fees $22743.32 Estimated Strategy Capacity $29000000.00 Lowest Capacity Asset INTC R735QTJ8XC9X Portfolio Turnover 22.79% |
# region imports
import openai
import pytz
import requests
import json
from datetime import timedelta
from AlgorithmImports import *
# endregion
class JumpingTanManatee(QCAlgorithm):
def Initialize(self):
self.SetCash(1000000)
self.SetStartDate(2021,1,1)
self.rebalanceTime = datetime.min
self.UniverseSettings.Resolution = Resolution.Daily
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel(portfolioBias=PortfolioBias.Long))
self.AddRiskManagement(NullRiskManagementModel())
self.SetExecution(ImmediateExecutionModel())
self.lastDateSaved = date.min
self.SetWarmUp(60)
self.Settings.FreePortfolioValuePercentage = 0.10 #cash buffer to 10%
self.index = self.AddEquity("IWV", Resolution.Daily)
self.AddUniverse(self.Universe.ETF(self.index.Symbol, self.UniverseSettings, self.Filter))
def Filter(self, constituents: List[ETFConstituentData]) -> List[Symbol]:
if self.Time < self.rebalanceTime:
return Universe.Unchanged
self.rebalanceTime = self.Time + timedelta(days=30)
active_symbols = [s.Symbol for s in self.ActiveSecurities.Values]
incoming_symbols = sorted([c for c in constituents if c.Weight], key=lambda c: c.Weight, reverse=True)[:50]
incoming_symbols = [c.Symbol for c in incoming_symbols]
grouped = sorted(list(set(active_symbols)) + list(incoming_symbols))
return list(set(active_symbols + incoming_symbols))
def OnSecuritiesChanged(self, changes):
for security in changes.AddedSecurities:
security.STD = self.STD(security.Symbol, 22)
security.ATR = self.ATR(security.Symbol, 22)
security.EMA = self.EMA(security.Symbol, 22)
identity = self.Identity(security.Symbol)
identity.Window.Size = 15
security.History = identity
def OnData(self, slice: Slice) -> None:
if not self.index.History.Window.IsReady:
return
trade_securities = []
signals = {'symbol': '', 'sentiment': [] }
for security in self.ActiveSecurities.Values:
if not security.History.Window.IsReady:
continue
if security.Symbol == self.index.Symbol or not hasattr(security, 'STD'):
continue
threshold = 2.5
std = threshold*security.STD.Current.Value
avg = security.EMA.Current.Value
if self.index.History[5] is not None and security.History[5] is not None and security.History[5].Value != 0:
factor = self.index.History[5].Value/security.History[5].Value
scaled_stockprice = factor*security.Close
divergence = 1 - scaled_stockprice/self.index.Close
divergence = abs(divergence)
if divergence > 0.03 and divergence < 0.20:
if (security.Close < (-std+avg)):
trade_securities.append(Insight.Price(security.Symbol, Resolution.Daily, 2, InsightDirection.Up))
if self.IsWarmingUp:
return
self.EmitInsights(trade_securities)