Package: pystockfilter
pystockfilterCreate your own fundamental or chart based stock filter. All you need is a database set up withpystockdb.built-in filterstechnical filtersADXRSIStockIsHot: Simple trend indicatorStockIsHotSecure: improved StockIsHot version.fundamental filtersLervermannPiotroski F-ScorePrice Target Score: analysts price targets compared with actual priceinstallpipinstallpystockfilterquick startBuild internal filters:importloggingfrompystockdb.db.schema.stocksimportdbfrompystockfilter.tool.build_internal_filtersimportBuildInternalFilters# connect to databasearguments={'db_args':{'provider':'sqlite','filename':db_path_test,'create_db':False}}db.bind(**arguments["db_args"])db.generate_mapping()# create internal filters for Adidas AG and Infineonarguments={'symbols':['ADS.F','IFX.F']}builder=BuildInternalFilters(arguments,logger)builder.build()# create internal filters for all stocks in databasearguments={'symbols':['ALL']}builder=BuildInternalFilters(arguments,logger)builder.build()Build custom filters:importloggingimportmathfromdatetimeimportdatetimeimportnumpyasnpimporttulipyastiimportyfinanceasyffromdateutil.relativedeltaimportrelativedeltafrompony.ormimportdb_session,selectfrompystockdb.db.schema.stocksimportPrice,Tagfrompystockfilter.filter.base_filterimportBaseFilterfrompystockfilter.base.base_helperimportBaseHelperfrompystockfilter.tool.build_filtersimportBuildFilters# custom filterclassDividendKings(BaseFilter):"""Calculates median of last dividends"""NAME='DividendKings'def__init__(self,arguments:dict,logger:logging.Logger):self.buy=arguments['args']['threshold_buy']self.sell=arguments['args']['threshold_sell']self.lookback=arguments['args']['lookback']self.max_yield=arguments['args']['max_div_yield']super(DividendKings,self).__init__(arguments,logger)@db_sessiondefanalyse(self):symbol=select(sym.nameforsyminself.stock.price_item.symbolsifTag.YAOinsym.item.tags.name).first()try:yao_item=yf.Ticker(symbol)data=yao_item.dividendsexceptValueError:raiseRuntimeError("Couldn't load dividends for{}".format(symbol))dates=data.index.arraydrop=[]# let us calculate the dividend yieldformy_dateindates:price=Price.select(lambdap:p.symbol.name==symbolandp.date.date()==my_date.date()).first()ifprice:div_yield=(data[my_date]/price.close)*100ifdiv_yield>self.max_yield:drop.append(my_date)self.logger.error('{}has a non plausible div yield at{}({}={}/{}* 100).'.format(symbol,my_date,div_yield,data[my_date],price.close))else:data[my_date]=div_yieldelse:drop.append(my_date)data=data.drop(labels=drop)self.calc=data.median(axis=0)ifself.calcisNoneormath.isnan(self.calc):raiseRuntimeError("Couldn't calculate dividend yield.")returnsuper(DividendKings,self).analyse()defget_calculation(self):returnself.calcdeflook_back_date(self):returnself.now_date+relativedelta(months=-self.lookback)logger=BaseHelper.setup_logger("custom filter")arguments_div={"name":"DividendKings","bars":False,"index_bars":False,"args":{"threshold_buy":3,"threshold_sell":0.2,"intervals":None,"max_div_yield":9,"lookback":2,},}symbols=["ADS.F","WDI.F","BAYN.F"]config_custom_filter={"symbols":symbols,"filters":[DividendKings(arguments_div,logger)],}custom=BuildFilters(config_custom_filter,logger)custom.build()issue trackerhttps://github.com/portfolioplus/pystockfilter/issuese