Stockcxx / src /classes /ConfigManager.py
jarvisx17's picture
Upload 46 files
9bf26a6 verified
'''
* Project : Screenipy
* Author : Pranjal Joshi
* Created : 28/04/2021
* Description : Class for managing the user configuration
'''
import sys
import os
import glob
import re
import configparser
from datetime import date
from classes.ColorText import colorText
parser = configparser.ConfigParser(strict=False)
# Default attributes for Downloading Cache from Git repo
default_period = '300d'
default_duration = '1d'
# This Class manages read/write of user configuration
class tools:
def __init__(self):
self.consolidationPercentage = 10
self.volumeRatio = 2
self.minLTP = 20.0
self.maxLTP = 50000
self.period = '300d'
self.duration = '1d'
self.daysToLookback = 30
self.shuffleEnabled = True
self.cacheEnabled = True
self.stageTwo = False
self.useEMA = False
def deleteStockData(self,excludeFile=None):
for f in glob.glob('stock_data*.pkl'):
if excludeFile is not None:
if not f.endswith(excludeFile):
os.remove(f)
else:
os.remove(f)
# Handle user input and save config
def setConfig(self, parser, default=False, showFileCreatedText=True):
if default:
parser.add_section('config')
parser.set('config', 'period', self.period)
parser.set('config', 'daysToLookback', str(self.daysToLookback))
parser.set('config', 'duration', self.duration)
parser.set('config', 'minPrice', str(self.minLTP))
parser.set('config', 'maxPrice', str(self.maxLTP))
parser.set('config', 'volumeRatio', str(self.volumeRatio))
parser.set('config', 'consolidationPercentage',
str(self.consolidationPercentage))
parser.set('config', 'shuffle', 'y')
parser.set('config', 'cacheStockData', 'y')
parser.set('config', 'onlyStageTwoStocks', 'y' if self.stageTwo else 'n')
parser.set('config', 'useEMA', 'y' if self.useEMA else 'n')
try:
fp = open('screenipy.ini', 'w')
parser.write(fp)
fp.close()
if showFileCreatedText:
print(colorText.BOLD + colorText.GREEN +
'[+] Default configuration generated as user configuration is not found!' + colorText.END)
print(colorText.BOLD + colorText.GREEN +
'[+] Use Option > 5 to edit in future.' + colorText.END)
print(colorText.BOLD + colorText.GREEN +
'[+] Close and Restart the program now.' + colorText.END)
input('')
sys.exit(0)
except IOError:
print(colorText.BOLD + colorText.FAIL +
'[+] Failed to save user config. Exiting..' + colorText.END)
input('')
sys.exit(1)
else:
parser = configparser.ConfigParser(strict=False)
parser.add_section('config')
print('')
print(colorText.BOLD + colorText.GREEN +
'[+] Screeni-py User Configuration:' + colorText.END)
self.period = input(
'[+] Enter number of days for which stock data to be downloaded (Days)(Optimal = 365): ')
self.daysToLookback = input(
'[+] Number of recent days (TimeFrame) to screen for Breakout/Consolidation (Days)(Optimal = 20): ')
self.duration = input(
'[+] Enter Duration of each candle (Days)(Optimal = 1): ')
self.minLTP = input(
'[+] Minimum Price of Stock to Buy (in RS)(Optimal = 20): ')
self.maxLTP = input(
'[+] Maximum Price of Stock to Buy (in RS)(Optimal = 50000): ')
self.volumeRatio = input(
'[+] How many times the volume should be more than average for the breakout? (Number)(Optimal = 2.5): ')
self.consolidationPercentage = input(
'[+] How many % the price should be in range to consider it as consolidation? (Number)(Optimal = 10): ')
self.shuffle = str(input(
'[+] Shuffle stocks rather than screening alphabetically? (Y/N): ')).lower()
self.cacheStockData = str(input(
'[+] Enable High-Performance and Data-Saver mode? (This uses little bit more CPU but performs High Performance Screening) (Y/N): ')).lower()
self.stageTwoPrompt = str(input(
'[+] Screen only for Stage-2 stocks?\n(What are the stages? => https://www.investopedia.com/articles/trading/08/stock-cycle-trend-price.asp)\n(Y/N): ')).lower()
self.useEmaPrompt = str(input(
'[+] Use EMA instead of SMA? (EMA is good for Short-term & SMA for Mid/Long-term trades)[Y/N]: ')).lower()
parser.set('config', 'period', self.period + "d")
parser.set('config', 'daysToLookback', self.daysToLookback)
parser.set('config', 'duration', self.duration + "d")
parser.set('config', 'minPrice', self.minLTP)
parser.set('config', 'maxPrice', self.maxLTP)
parser.set('config', 'volumeRatio', self.volumeRatio)
parser.set('config', 'consolidationPercentage',
self.consolidationPercentage)
parser.set('config', 'shuffle', self.shuffle)
parser.set('config', 'cacheStockData', self.cacheStockData)
parser.set('config', 'onlyStageTwoStocks', self.stageTwoPrompt)
parser.set('config', 'useEMA', self.useEmaPrompt)
# delete stock data due to config change
self.deleteStockData()
print(colorText.BOLD + colorText.FAIL + "[+] Cached Stock Data Deleted." + colorText.END)
try:
fp = open('screenipy.ini', 'w')
parser.write(fp)
fp.close()
print(colorText.BOLD + colorText.GREEN +
'[+] User configuration saved.' + colorText.END)
print(colorText.BOLD + colorText.GREEN +
'[+] Restart the Program to start Screening...' + colorText.END)
input('')
sys.exit(0)
except IOError:
print(colorText.BOLD + colorText.FAIL +
'[+] Failed to save user config. Exiting..' + colorText.END)
input('')
sys.exit(1)
# Load user config from file
def getConfig(self, parser):
if len(parser.read('screenipy.ini')):
try:
self.duration = parser.get('config', 'duration')
self.period = parser.get('config', 'period')
self.minLTP = float(parser.get('config', 'minprice'))
self.maxLTP = float(parser.get('config', 'maxprice'))
self.volumeRatio = float(parser.get('config', 'volumeRatio'))
self.consolidationPercentage = float(
parser.get('config', 'consolidationPercentage'))
self.daysToLookback = int(
parser.get('config', 'daysToLookback'))
if 'n' not in str(parser.get('config', 'shuffle')).lower():
self.shuffleEnabled = True
if 'n' not in str(parser.get('config', 'cachestockdata')).lower():
self.cacheEnabled = True
if 'n' not in str(parser.get('config', 'onlyStageTwoStocks')).lower():
self.stageTwo = True
else:
self.stageTwo = False
if 'y' not in str(parser.get('config', 'useEMA')).lower():
self.useEMA = False
else:
self.useEMA = True
except configparser.NoOptionError:
input(colorText.BOLD + colorText.FAIL +
'[+] Screenipy requires user configuration again. Press enter to continue..' + colorText.END)
parser.remove_section('config')
self.setConfig(parser, default=False)
else:
self.setConfig(parser, default=True)
# Print config file
def showConfigFile(self):
try:
f = open('screenipy.ini', 'r')
print(colorText.BOLD + colorText.GREEN +
'[+] Screeni-py User Configuration:' + colorText.END)
print("\n"+f.read())
f.close()
input('')
except:
print(colorText.BOLD + colorText.FAIL +
"[+] User Configuration not found!" + colorText.END)
print(colorText.BOLD + colorText.WARN +
"[+] Configure the limits to continue." + colorText.END)
self.setConfig(parser)
# Check if config file exists
def checkConfigFile(self):
try:
f = open('screenipy.ini','r')
f.close()
return True
except FileNotFoundError:
return False
# Get period as a numeric value
def getPeriodNumeric(self):
import re
pattern = re.compile(r'\d+')
result = [int(match.group()) for match in pattern.finditer(self.period)][0]
return result