Overall Statistics
Total Trades
287
Average Win
2.35%
Average Loss
-1.25%
Compounding Annual Return
1.614%
Drawdown
32.200%
Expectancy
0.047
Net Profit
6.616%
Sharpe Ratio
0.155
Probabilistic Sharpe Ratio
2.087%
Loss Rate
64%
Win Rate
36%
Profit-Loss Ratio
1.88
Alpha
0.002
Beta
0.157
Annual Standard Deviation
0.115
Annual Variance
0.013
Information Ratio
-0.586
Tracking Error
0.145
Treynor Ratio
0.114
Total Fees
$30315.13
Estimated Strategy Capacity
$440000.00
Lowest Capacity Asset
O R735QTJ8XC9X
from LimitOrdersAlphaModel import LimitOrdersAlphaModelConfig
from LimitOrdersAlphaModel import LimitOrdersAlphaModel

RESOLUTION = Resolution.Minute
STARTING_CASH = 1000000

O = Symbol.Create("O", SecurityType.Equity, Market.USA)

O_LimitOrdersAlphaModelConfig = LimitOrdersAlphaModelConfig(O)

class WeightedConstructionModel(PortfolioConstructionModel):
    def CreateTargets(self, algorithm, insights):
        targets = []
        for insight in insights:
            targets.append(PortfolioTarget.Percent(algorithm, insight.Symbol, insight.Weight))
        return targets
  
class LimitSpreadExecutionModel(ExecutionModel):

    def __init__(self, acceptingSpreadPercent=0.005):
        self.targetsCollection = PortfolioTargetCollection()
        self.acceptingSpreadPercent = Math.Abs(acceptingSpreadPercent)

    def Execute(self, algorithm, targets):
        self.targetsCollection.AddRange(targets)

        if self.targetsCollection.Count > 0:
            for target in self.targetsCollection.OrderByMarginImpact(algorithm):
                symbol = target.Symbol
                
                unorderedQuantity = OrderSizing.GetUnorderedQuantity(algorithm, target)
                
                if unorderedQuantity != 0:
                    security = algorithm.Securities[symbol]
                    if self.SpreadIsFavorable(security):
                        #algorithm.MarketOrder(symbol, unorderedQuantity)
                        if unorderedQuantity > 0:
                            algorithm.LimitOrder(symbol, unorderedQuantity, security.Close * 1.1)
                        elif unorderedQuantity < 0:
                            algorithm.LimitOrder(symbol, unorderedQuantity, security.Close * 0.9)

            self.targetsCollection.ClearFulfilled(algorithm)
            
    def SpreadIsFavorable(self, security):
        return security.Exchange.ExchangeOpen \
            and security.Price > 0 and security.AskPrice > 0 and security.BidPrice > 0 \
            and (security.AskPrice - security.BidPrice) / security.Price <= self.acceptingSpreadPercent
            
            
class Fullblend(QCAlgorithm):

    def Initialize(self):
        self.SetBrokerageModel(BrokerageName.AlphaStreams)
        self.SetCash(STARTING_CASH) 
        self.SetStartDate(2016, 1, 1)
        self.SetEndDate(2020, 1, 1)
        
        # entire tradable universe
        self.UniverseSettings.Resolution = RESOLUTION
        self.AddUniverseSelection(ManualUniverseSelectionModel([O]))
        
        # set alpha models
        self.AddAlpha(LimitOrdersAlphaModel(self, O_LimitOrdersAlphaModelConfig))

        # set portfolio weightings
        self.SetPortfolioConstruction(WeightedConstructionModel())
        
        # set execution model
        self.SetExecution(LimitSpreadExecutionModel())
        
        # set risk management model
        self.AddRiskManagement(NullRiskManagementModel())
import numpy as np

class LimitOrdersAlphaModelConfig:
    def __init__(self, 
        SYMBOL
    ):
        if not SYMBOL:
            raise ValueError("[{}] No symbol".format(self.__class__.__name__))
        
        self.SYMBOL = SYMBOL

class LimitOrdersAlphaModel(AlphaModel):
    def __init__(self, algorithm, CONFIG):
        self.algorithm = algorithm
        self.config = CONFIG
        
        self.symbol = CONFIG.SYMBOL
        self.symbol_roc = RateOfChange(20)
        self.weight = 1.0
        
        self.Warmup(
            [self.symbol], 
            30, 
            Resolution.Hour, 
            [self.symbol_roc], 
        )
        
    def Warmup(self, symbols, lookback, resolution, indicators):
        history = self.algorithm.History(symbols, lookback, Resolution.Hour)
        for time, row in history["close"].unstack(level = 0).iterrows():
            indicators[0].Update(time, row[symbols[0]])

            
    def Update(self, algorithm, data):
        insights = []
        if algorithm.Time.minute == 0:
            if (self.symbol in data.Bars):
                self.symbol_roc.Update(algorithm.Time, data.Bars[self.symbol].Close)

            cutloss = algorithm.Securities[self.symbol].Holdings.UnrealizedProfitPercent < -0.05
            if algorithm.Portfolio[self.symbol].Quantity != 0 and cutloss:
                insights.append(Insight.Price(self.symbol, timedelta(minutes = 300), InsightDirection.Flat, None, None, None, 0.00))
                
            if algorithm.Time.hour == 10:
                if (self.symbol_roc.Current.Value > 0):
                    if algorithm.Portfolio[self.symbol].Quantity == 0:
                        insights.append(Insight.Price(self.symbol, timedelta(minutes = 300), InsightDirection.Up, None, None, None, self.weight))
                elif algorithm.Portfolio[self.symbol].Quantity != 0:
                    insights.append(Insight.Price(self.symbol, timedelta(minutes = 300), InsightDirection.Flat, None, None, None, 0.00))

        return Insight.Group(insights)