Overall Statistics
Total Orders
0
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Start Equity
50000
End Equity
50000
Net Profit
0%
Sharpe Ratio
0
Sortino 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
0
Tracking Error
0
Treynor Ratio
0
Total Fees
$0.00
Estimated Strategy Capacity
$0
Lowest Capacity Asset
Portfolio Turnover
0%
from AlgorithmImports import *
from QuantConnect.DataSource import *
import math
#endregion
import datetime 
import calendar
import numpy 
class StockSelectionStrategyBasedOnFundamentalFactorsAlgorithm(QCAlgorithm):

    def Initialize(self):
        self.todaysDate = 22
        self.thisMonth = 11
        self.thisYear = 2024
        
        
        self.SetStartDate(self.thisYear, self.thisMonth, self.todaysDate)  # Set Start Date
        self.SetEndDate(self.thisYear, self.thisMonth, self.todaysDate)    # Set End Date
        self.SetCash(50000)          # Set Strategy Cash

        self.roe = {}
        self.rsRating = {}
        self.weightedRoc = {}
        self.sortedSymbol = []
        self.weight1 = 3
        self.weight2 = 2
        self.weight3 = 2
        self.weight4 = 3
        self.topXPercent = 0.2
        self.volumeThreshold = 1000000
        self.priceThreshold = 10

        self.AddUniverse(self.CoarseSelectionFunction)
        self.universe_settings.resolution = Resolution.Daily
        self.Debug("==================")

    def CoarseSelectionFunction(self, fine):
        self.Debug("-------------")
        fine = [x for x in fine if  x.HasFundamentalData and  x.earning_reports.diluted_eps.twelve_months]
        sorted_by_volume = sorted(fine, key=lambda x: x.dollar_volume, reverse=True)
        sorted_by_volume = [x.Symbol for x in sorted_by_volume]
        return sorted_by_volume
        
        
    def OnData(self, data):
        for symbol, tradeBar in data.bars.items():
            history = self.History(symbol, 252, Resolution.Daily)
            count = 1
            closeList = []
            for time, row in history.loc[symbol].iterrows():
                if count == 1 or count == 121 or count == 189 or count == 229:
                    closeList.append(row['close'])
                if count == 252:
                    roc1 = self.roc(closeList[0],row['close'])
                    roc2 = self.roc(closeList[1],row['close'])
                    roc3 = self.roc(closeList[2],row['close'])
                    roc4 = self.roc(closeList[3],row['close'])
                    self.weightedRoc[symbol] = roc1 * self.weight1 + roc2 * self.weight2 +  roc3 * self.weight3 + roc4 * self.weight4
                count += 1
        self.weightedRoc = {k: v for k, v in sorted(self.weightedRoc.items(), key=lambda x: x[1])} 
        count = 0
        for k, v in self.weightedRoc.items():
            self.sortedSymbol.append(k)
        symbolSize = len(self.sortedSymbol)
        for j in range(symbolSize):
            self.rsRating[self.sortedSymbol[j]] = ((j + 1) / symbolSize)
            self.rsRating = {k: v for k, v in sorted(self.rsRating.items(), key=lambda x: x[1], reverse=True)}
        numberOfTopPercent = symbolSize * self.topXPercent
        rsCount= 1
        # sma filter
        outputList = []
        for symbol in self.rsRating.keys():
            if rsCount > numberOfTopPercent:
                    break
            history = self.History(symbol, 252, Resolution.Daily)
            max = -1
            min = 999999
            closeList = []
            volumeList = []
            for time, row in history.loc[symbol].iterrows():
                volumeList.append(row['volume'])
                closeList.append(row['close'])
                if row['high'] > max:
                    max = row['high']
                if row['low'] < min: 
                    min = row['low']
            if numpy.average(volumeList) > self.volumeThreshold and closeList[0] > self.priceThreshold:
                closeList.reverse()
                dmax = (closeList[0] - max) / max
                dmin = (closeList[0] - min) / min
                if dmax < 0.25:
                    if dmin > 0.3:
                        #sma
                        tempList = closeList[:50]
                        sma50 = numpy.average(tempList)
                        tempList = closeList[:150]
                        sma150 = numpy.average(tempList)
                        tempList = closeList[:200]
                        sma200 = numpy.average(tempList)
                        if closeList[0] > sma50 and sma50 > sma200 and sma50 > sma150 and sma150 > sma200:
                            outputList.append(symbol.value)

            rsCount+=1
        self.debug(outputList)
        return 
        

    def roc(self, old, new):
        result = ((new - old) / old)
        return result