| Overall Statistics |
|
Total Trades 14 Average Win 1.06% Average Loss -4.87% Compounding Annual Return -9.142% Drawdown 9.500% Expectancy -0.188 Net Profit -5.639% Sharpe Ratio -1.016 Probabilistic Sharpe Ratio 1.515% Loss Rate 33% Win Rate 67% Profit-Loss Ratio 0.22 Alpha -0.073 Beta 0 Annual Standard Deviation 0.072 Annual Variance 0.005 Information Ratio -0.611 Tracking Error 0.378 Treynor Ratio 2090.975 Total Fees $20.13 Estimated Strategy Capacity $450000000.00 |
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Algorithm.Framework")
AddReference("QuantConnect.Common")
from QuantConnect import *
from QuantConnect.Parameters import *
from QuantConnect.Benchmarks import *
from QuantConnect.Brokerages import *
from QuantConnect.Util import *
from QuantConnect.Interfaces import *
from QuantConnect.Algorithm import *
from QuantConnect.Algorithm.Framework import *
from QuantConnect.Algorithm.Framework.Selection import *
from QuantConnect.Algorithm.Framework.Alphas import *
from QuantConnect.Algorithm.Framework.Portfolio import *
from QuantConnect.Algorithm.Framework.Execution import *
from QuantConnect.Algorithm.Framework.Risk import *
from QuantConnect.Indicators import *
from QuantConnect.Data import *
from QuantConnect.Data.Consolidators import *
from QuantConnect.Data.Custom import *
from QuantConnect.Data.Fundamental import *
from QuantConnect.Data.Market import *
from QuantConnect.Data.UniverseSelection import *
from QuantConnect.Notifications import *
from QuantConnect.Orders import *
from QuantConnect.Orders.Fees import *
from QuantConnect.Orders.Fills import *
from QuantConnect.Orders.Slippage import *
from QuantConnect.Scheduling import *
from QuantConnect.Securities import *
from QuantConnect.Securities.Equity import *
from QuantConnect.Securities.Forex import *
from QuantConnect.Securities.Interfaces import *
from datetime import date, datetime, timedelta
from QuantConnect.Python import *
from QuantConnect.Storage import *
QCAlgorithmFramework = QCAlgorithm
QCAlgorithmFrameworkBridge = QCAlgorithm
import calendar
class FirstDaySPY(QCAlgorithmFramework):
"""Buy on close on the last day of the month and sell on the close of the next day"""
def Initialize(self):
self.SetStartDate(2020, 1, 28) # Set Start Date
self.SetEndDate(2020, 9, 5)
self.SetCash(100000) # Set Strategy Cash
# Parameters
self.maximumDuration = 1 # maximum duration to keep trades open
# Universe
self.UniverseSettings.Resolution = Resolution.Daily
# symbols = [ Symbol.Create("SPY", SecurityType.Equity, Market.USA) ]
self.AddEquity("SPY", Resolution.Daily)
# self.AddUniverseSelection( ManualUniverseSelectionModel(symbols) )
# self.AddUniverseSelection(CoarseFundamentalUniverseSelectionModel(self.SelectCoarse))
self.AddAlpha(FirstDayAlphaModel())
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
self.AddRiskManagement(FixedDurationTrades(self.maximumDuration))
# TODO: verify this, I want to buy on close at the end of the last day and sell on close of the next day
self.SetExecution(ImmediateExecutionModel())
def SelectCoarse(self, coarse):
self.Debug(f"In universe selection time: {self.Time}")
# TODO: smooth that
sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)
isETF = [x.Symbol for x in sortedByDollarVolume if not x.HasFundamentalData]
self.Debug(f"Total coarse stocks: {len(sortedByDollarVolume)} and total nonFundamental: {len(isETF)}")
return isETF[:10]
def OnSecuritiesChanged(self, changes):
self._changes = changes
self.Debug(f"OnSecuritiesChanged({self.UtcTime}):: {changes}")
self.Log(f"OnSecuritiesChanged({self.UtcTime}):: {changes}")
# def OnData(self, data):
# """OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
# Arguments:
# data: Slice object keyed by symbol containing the stock data
# """
# # if not self.Portfolio.Invested:
# # self.SetHoldings("SPY", 1)
# # self.Debug("Purchased Stock")
class FixedDurationTrades(RiskManagementModel):
def __init__(self, maximumDuration = 1):
"""Provides an implementation of IRiskManagementModel that limits the maximum number of periods
that we can stay in a trade"""
self.maximumDuration = maximumDuration
self.investedTime = {}
def ManageRisk(self, algorithm, targets):
riskAdjustedTargets = list()
for kvp in algorithm.Securities:
symbol = kvp.Key
security = kvp.Value
# Remove if not invested
if not security.Invested:
self.investedTime.pop(symbol, None)
continue
# Add newly invested securities
if symbol not in self.investedTime:
self.investedTime[symbol] = 0 # Set to 0 periods invested
continue
self.investedTime[symbol] += 1
if self.investedTime[symbol] >= self.maximumDuration:
# liquidate securities that have reached max duration
riskAdjustedTargets.append(PortfolioTarget(symbol, 0.))
algorithm.Debug(f"Setting liquidation target for {symbol}")
return riskAdjustedTargets
class FirstDayAlphaModel(AlphaModel):
Name = "FirstDayAlphaModel"
def Update(self, algorithm, slice):
# Updates this alpha model with the latest data from the algorithm.
# This is called each time the algorithm receives data for subscribed securities
# Generate insights on the securities in the universe.
insights = []
DateRules.MonthEnd
algorithm.Debug(f"Inside Alpha Model at time: {algorithm.Time}")
symbols = list(algorithm.ActiveSecurities.Keys)
algorithm.Debug(f"Active symbols: {[s.Value for s in symbols]}")
# insight expiry time and direction
insightExpiry = Expiry.EndOfDay(algorithm.Time)
insightDirection = InsightDirection.Up # insight direction
# TODO: weight by how many often this worked in the past
for symbol in symbols:
# add insights if it's the last tradable day of the month
if list(algorithm.DateRules.MonthEnd(symbol, 0).GetDates(algorithm.Time, algorithm.Time)):
algorithm.Debug(f"Last Day of the month, Emit insight for symbol {symbol.Value}")
insights.append(Insight.Price(symbol, insightExpiry, insightDirection,
None, None, None, None))
return insights
def OnSecuritiesChanged(self, algorithm, changes):
# Handle security changes in from your universe model.
pass