Overall Statistics
Total Trades
0
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Net Profit
0%
Sharpe Ratio
0
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
-19.439
Tracking Error
0.132
Treynor Ratio
0
Total Fees
$0.00
Estimated Strategy Capacity
$0
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, 8, 29)  # Set Start Date
        self.SetEndDate(2020, 9, 2)  
        self.SetCash(100000)  # Set Strategy Cash

        # Parameters
        self.maximumDuration = 1  # maximum duration to keep trades open

        # Universe
        self.UniverseSettings.Resolution = Resolution.Daily
        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())
        self.Debug("test")

    def SelectCoarse(self, coarse):
        self.Debug(f"Select coarse time: {self.Time}")
        sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)
        isETF = [x.Symbol for x in sortedByDollarVolume if not x.HasFundamentalData]
        self.Debug(f"{len(sortedByDollarVolume)} and {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.))
                self.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 = []
        if algorithm.Time.day == calendar.monthrange(algorithm.Time.year, algorithm.Time.month):
            algorithm.Log("Last Day of the month, emit Insight")
            symbols = [s.Symbol for s in algorithm.ActiveSecurities]
            # 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:
                algorithm.Debug("Emit insight UP for symbol {symbol}")
                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