Overall Statistics
Total Trades
500
Average Win
0.08%
Average Loss
-0.08%
Compounding Annual Return
0.831%
Drawdown
2.000%
Expectancy
0.023
Net Profit
0.414%
Sharpe Ratio
0.329
Probabilistic Sharpe Ratio
31.750%
Loss Rate
49%
Win Rate
51%
Profit-Loss Ratio
1.00
Alpha
-0.006
Beta
0.05
Annual Standard Deviation
0.026
Annual Variance
0.001
Information Ratio
-2.194
Tracking Error
0.131
Treynor Ratio
0.171
Total Fees
$560.00
Estimated Strategy Capacity
$21000000.00
Lowest Capacity Asset
SPY R735QTJ8XC9X
from CustomInsightWeightingPortfolioConstructionModel import CustomInsightWeightingPortfolioConstructionModel

class JumpingRedPenguin(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2021, 1, 18)
        self.SetCash(100000) 
        self.AddEquity("SPY", Resolution.Minute)

        self.AddAlpha(Alpha1())
        self.AddAlpha(Alpha2())
        
        self.SetPortfolioConstruction(CustomInsightWeightingPortfolioConstructionModel())
        
    
class Alpha1(AlphaModel):
    
    def __init__(self):
        self.Name = "Long"
        
    def Update(self, algorithm, data):
        if algorithm.Time.hour == 9 and algorithm.Time.minute == 31:
            return [Insight.Price("SPY", timedelta(minutes = 20), InsightDirection.Up, None, None, None, 0.5)]
        return []
        
class Alpha2(AlphaModel):
    
    def __init__(self):
        self.Name = "Short"
        
    def Update(self, algorithm, data):
        if algorithm.Time.hour == 10 and algorithm.Time.minute == 31:
            return [Insight.Price("SPY", timedelta(minutes = 20), InsightDirection.Up, None, None, None, 1.)]
        return []
from clr import AddReference
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Algorithm.Framework")

from QuantConnect import *
from QuantConnect.Algorithm.Framework.Alphas import *
from EqualWeightingPortfolioConstructionModel import EqualWeightingPortfolioConstructionModel, PortfolioBias

class CustomInsightWeightingPortfolioConstructionModel(EqualWeightingPortfolioConstructionModel):
    
    def __init__(self, rebalance = Resolution.Daily, portfolioBias = PortfolioBias.LongShort):
        super().__init__(rebalance, portfolioBias)

    def ShouldCreateTargetForInsight(self, insight):
        # Ignore insights that don't have Weight value
        return insight.Weight is not None

    def DetermineTargetPercent(self, activeInsights):
        result = {}

        # We will adjust weights proportionally in case the sum is > 1 so it sums to 1.
        weightSums = sum(self.GetValue(insight) for insight in activeInsights if self.RespectPortfolioBias(insight))
        weightFactor = 1.0
        if weightSums > 1:
            weightFactor = 1 / weightSums
        for insight in activeInsights:
            result[insight] = (insight.Direction if self.RespectPortfolioBias(insight) else InsightDirection.Flat) * self.GetValue(insight) * weightFactor
        return result

    def GetValue(self, insight):
        # adjust by alpha model
        if insight.SourceModel == "Long":
            factor = 0.5
        elif insight.SourceModel == "Short":
            factor = 2
            
        return insight.Weight * factor
from clr import AddReference
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Algorithm.Framework")

from QuantConnect import *
from QuantConnect.Algorithm.Framework.Alphas import *
from QuantConnect.Algorithm.Framework.Portfolio import *
from itertools import groupby
from datetime import datetime, timedelta

class EqualWeightingPortfolioConstructionModel(PortfolioConstructionModel):
    '''Provides an implementation of IPortfolioConstructionModel that gives equal weighting to all securities.
    The target percent holdings of each security is 1/N where N is the number of securities.
    For insights of direction InsightDirection.Up, long targets are returned and
    for insights of direction InsightDirection.Down, short targets are returned.'''

    def __init__(self, rebalance = Resolution.Daily, portfolioBias = PortfolioBias.LongShort):
        '''Initialize a new instance of EqualWeightingPortfolioConstructionModel
        Args:
            rebalance: Rebalancing parameter. If it is a timedelta, date rules or Resolution, it will be converted into a function.
                              If None will be ignored.
                              The function returns the next expected rebalance time for a given algorithm UTC DateTime.
                              The function returns null if unknown, in which case the function will be called again in the
                              next loop. Returning current time will trigger rebalance.
            portfolioBias: Specifies the bias of the portfolio (Short, Long/Short, Long)'''
        self.portfolioBias = portfolioBias

        # If the argument is an instance of Resolution or Timedelta
        # Redefine rebalancingFunc
        rebalancingFunc = rebalance
        if isinstance(rebalance, int):
            rebalance = Extensions.ToTimeSpan(rebalance)
        if isinstance(rebalance, timedelta):
            rebalancingFunc = lambda dt: dt + rebalance
        if rebalancingFunc:
            self.SetRebalancingFunc(rebalancingFunc)

    def DetermineTargetPercent(self, activeInsights):
        '''Will determine the target percent for each insight
        Args:
            activeInsights: The active insights to generate a target for'''
        result = {}

        # give equal weighting to each security
        count = sum(x.Direction != InsightDirection.Flat and self.RespectPortfolioBias(x) for x in activeInsights)
        percent = 0 if count == 0 else 1.0 / count
        for insight in activeInsights:
            result[insight] = (insight.Direction if self.RespectPortfolioBias(insight) else InsightDirection.Flat) * percent
        return result

    def RespectPortfolioBias(self, insight):
        '''Method that will determine if a given insight respects the portfolio bias
        Args:
            insight: The insight to create a target for
        '''
        return self.portfolioBias == PortfolioBias.LongShort or insight.Direction == self.portfolioBias