Overall Statistics
Total Trades
1006
Average Win
0.00%
Average Loss
0.00%
Compounding Annual Return
-9.877%
Drawdown
13.700%
Expectancy
-0.020
Net Profit
-2.281%
Sharpe Ratio
-0.135
Probabilistic Sharpe Ratio
26.256%
Loss Rate
53%
Win Rate
47%
Profit-Loss Ratio
1.07
Alpha
0.215
Beta
1.41
Annual Standard Deviation
0.262
Annual Variance
0.069
Information Ratio
0.988
Tracking Error
0.144
Treynor Ratio
-0.025
Total Fees
$1122.26
Estimated Strategy Capacity
$11000000.00
Lowest Capacity Asset
PBI R735QTJ8XC9X
Portfolio Turnover
3.19%
from AlgorithmImports import *
import datetime
import pandas as pd
from io import StringIO 


class AlertBlueLemur(QCAlgorithm):

    def Initialize(self):
        # set up
        self.SetStartDate(2021, 12, 14)
        self.SetEndDate(2022, 3, 5)
        self.SetCash(1000000)

        # selection will run on the begining of the month
        self.spy = self.AddEquity("SPY", Resolution.Daily).Symbol
        self.SetBenchmark(self.spy)
        self.UniverseSettings.Resolution = Resolution.Daily
        self.AddUniverse("my-blob-universe", self.SelectSymbols)

        # init
        self.backtestSymbolsPerDay = {}
        self.backtestSymbolsPerDayLong = {}
        self.current_universe = []
        self.current_universe_long = []

    def SelectSymbols(self, date):
        
        # handle live mode file format
        if self.LiveMode:
            # fetch the file from dropbox
            str = self.Download("https://www.dropbox.com/s/2l73mu97gcehmh7/daily-stock-picker-live.csv?dl=1")
            # if we have a file for today, return symbols, else leave universe unchanged
            self.current_universe = str.split(',') if len(str) > 0 else self.current_universe
            return self.current_universe

        # backtest - first cache the entire file
        if len(self.backtestSymbolsPerDay) == 0:

            # str = self.Download("https://www.dropbox.com/s/ae1couew5ir3z9y/daily-stock-picker-backtest.csv?dl=1", headers)
            str_ = self.Download("https://snpmarketdata.blob.core.windows.net/qc-backtest/fundamental_stat_arb.csv")
            for line in str_.splitlines():
                data = line.split(',')
                pairs_short = data[1].split("|")
                pairs_long = data[2].split("|")
                self.backtestSymbolsPerDay[data[0]] = pairs_short + pairs_long
                self.backtestSymbolsPerDayLong[data[0]] = pairs_long

        index = date.strftime("%Y-%m-%d")
        if index not in self.backtestSymbolsPerDay:
            return Universe.Unchanged
        # self.current_universe = [Symbol.Create(x, SecurityType.Equity, Market.USA) for x in tickers if x not in ["|", " "]]
        self.current_universe = self.backtestSymbolsPerDay.get(index, self.current_universe)
        self.current_universe_long = self.backtestSymbolsPerDayLong.get(index, self.current_universe_long)

        #self.Debug(f" Universe {self.current_universe}")
        #self.Debug(f" Universe long {self.current_universe_long}")

        return self.current_universe

    def OnSecuritiesChanged(self, changes):
        self.changes = changes

    def OnData(self, slice):

        # if slice.Bars.Count == 0: return
        # if self.changes is None: return

        # start fresh
        # self.Liquidate()

        # trade
        if len(self.current_universe_long) == 0: return
        weight = 1 / len(self.current_universe_long)
        #self.Debug(f"weight {weight}")

        #self.Debug(f"Universe long {self.current_universe_long}")
        for symbol in self.current_universe_long:
            symbol1 = [x for x in self.Securities.Keys if x.Value == symbol][0]
            #self.Debug(f"Symbol 1 {symbol}")
            if not slice.ContainsKey(symbol1): continue
            #self.Debug(f"Symbol 2 {symbol}")
            if slice[symbol1] is None: continue
            #self.Debug(f"Symbol 3 {symbol}")
            self.SetHoldings(symbol1, weight)

        self.changes = None