File size: 9,393 Bytes
9bf26a6 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
'''
* 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
|