Skip to content

Commit

Permalink
updating staged changes
Browse files Browse the repository at this point in the history
updating staged changes
  • Loading branch information
Kheiden committed Jan 26, 2021
1 parent 840a6b1 commit ed2dbef
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 98 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ db.configure_database()
4) Obtain an Oauth access token from the Traider Developer web portal and add the `oauth_access_token` to `config_data_Dev.json`
5) Start the stock scan with the following code:
```
scanner = optionstracer.Scanner()
scanner = optionstrader.Scanner()
scanner.start_stock_scan()
```
6) After the stock data is finished, you can start the option chain scan with the following:
Expand Down
6 changes: 4 additions & 2 deletions optionstrader/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ def __init__(self):
except Exception as e:
msg = "Error! Please check the MySQL database connection: {error}".format(error=e)
self.log.debug(msg)
log_msg = msg
print(msg)
raise Exception

# CONFIGURATION
# Possible Values: "Dev", "Stage", "Production"
Expand Down Expand Up @@ -62,7 +63,8 @@ def create_new_account(self, account_type, initial_deposit):

# We want a random 20 digit number. Any leading zeroes will be appended
# to the account number on the database side.

if not account_type in ['checking', 'savings']:
return False
data = {}

account_number = str(random.randint(pow(10,20), pow(10,21)-1))
Expand Down
1 change: 1 addition & 0 deletions optionstrader/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ def analyze_single_option_chain(self, option_chain):

percentage_increase_analysis['symbol'] = symbol
#log_msg = "symbol: {}".format(symbol)
percentage_increase_analysis['option_type'] = option_chain['option_type']

percentage_increase_analysis['stock_price_increase'] = stock_price_increase
#log_msg = "stock_price_increase: {}".format(stock_price_increase)
Expand Down
2 changes: 1 addition & 1 deletion optionstrader/config_data/config_data_Dev.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"api_url": "https://sandbox.tradier.com/v1/", "api_url_streaming": "https://stream.tradier.com/v1/", "timestamp": 1520038541, "minimum_contract_cost_threshold": 5.0, "oauth_access_token_secret": "<Does Not Exist Yet>", "environment": "dev", "config_file_logging": "True", "oauth_access_token": "ABKDcnPB3zC1SKaX8akuvmGo9zo1"}
{"api_url": "https://sandbox.tradier.com/v1/", "api_url_streaming": "https://stream.tradier.com/v1/", "timestamp": 1520038541, "minimum_contract_cost_threshold": 5.0, "oauth_access_token_secret": "<Does Not Exist Yet>", "environment": "dev", "config_file_logging": "True", "oauth_access_token": "nW18CIaX5Bc1Zny1QaOJAzpFYwi9"}
62 changes: 37 additions & 25 deletions optionstrader/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@
from optionstrader.customlogging import CustomLog
from optionstrader.parser import Parser

MYSQL_IP_ADDR = '192.168.1.10'
# Used to debug via logs
DEBUG = False
class Database:

def __init__(self):
"""
There's some confusion with database vs table.
We will have separate environments for Dev/Stage and Prd,
so we will want to ensure that the databases are seperate.
so we will want to ensure that the databases are separate.
TODO: Ensure that the Dev/Stage and Prod environments are fully seggregared
TODO: Ensure that the Dev/Stage and Prod environments are fully seggregated
with their own databases. This will allows us to migrate the databases when
the time comes.
Expand All @@ -30,21 +33,7 @@ def __init__(self):

self.log = CustomLog()
self.parser = Parser()

try:
# Using loopback for testing purposes. Might use socket level later.
self.connection = mysql.connector.connect(user='root', password='root',
host='localhost',
port='3306')
#database='algotrader_data'

#mysql.connector.errors.InterfaceError: 2003: Can't connect to MySQL server on 'localwhost:3306'

except Exception as e:
msg = "Error! Please check the MySQL database connection: {error}".format(error=e)
self.log.debug(msg)
log_msg = msg

self.connection = self.connect_to_database()
# CONFIGURATION
# Possible Values: "Dev", "Stage", "Production"
# Changebelow code when config file exists
Expand All @@ -55,6 +44,20 @@ def __init__(self):
# Instead, we would rather query the database and only select the records that
# are within the threshold

def connect_to_database(self):
# try:
# Using loopback for testing purposes. Might use socket level later.
return mysql.connector.connect(user='optionstrader_service_account', password='helloworld',
host=MYSQL_IP_ADDR,
port='3306')
#database='algotrader_data'

#mysql.connector.errors.InterfaceError: 2003: Can't connect to MySQL server on 'localwhost:3306'

# except Exception as e:
# msg = "Error! Please check the MySQL database connection: {error}".format(error=e)
# self.log.debug(msg)

def configure_database(self):
database_name = "algotrader_dev"
self.create_database(database_name)
Expand All @@ -75,11 +78,12 @@ def configure_database(self):
table_name = "optionchainanalysis"
self.create_table(database_name, table_name, table_columns)

self.parse_symbols_and_add_to_db()
print("Database has been configured")
# self.parse_symbols_and_add_to_db()
self.log.debug("Database has been configured")
return True

def create_database(self, database_name):
try:
cursor = self.connection.cursor()
query = ("CREATE DATABASE {database_name}").format(database_name=database_name)
cursor.execute(query)
Expand All @@ -88,10 +92,14 @@ def create_database(self, database_name):
msg = "Database `{database_name}` created.".format(
database_name=database_name)
self.log.debug(msg)
print(msg)
return True
except:
msg = "Database `{database_name}` can't be created.".format(
database_name=database_name)
self.log.debug(msg)

def create_table(self, database_name, table_name, table_columns):
try:
cursor = self.connection.cursor()
query = "CREATE TABLE {database_name}.{table_name} {table_columns}".format(
database_name=database_name,
Expand All @@ -104,8 +112,11 @@ def create_table(self, database_name, table_name, table_columns):
database_name=database_name,
table_name=table_name)
self.log.debug(msg)
print(msg)
return True
except:
msg = "Table `{table_name}` can't be created.".format(
table_name=table_name)
self.log.debug(msg)

def close_connection(self):
self.connection.close()
Expand Down Expand Up @@ -184,6 +195,7 @@ def get_list_of_tickers(self, query_type='default'):
# As of 2/11/17, there are 3078 total results from this query
self.connection.commit()
result = cursor.execute(query)
print(result)
list_of_tickers = list()
for ticker in cursor:
#print(ticker[0])
Expand Down Expand Up @@ -215,7 +227,6 @@ def get_example_option_chains(self, num_chains_limit=1):
self.connection.commit()
cursor.execute(query)


self.log.debug("****Type:{0}".format(type(cursor)))
return cursor
# Only iterate once
Expand Down Expand Up @@ -339,8 +350,10 @@ def save_option_chain_to_table(self, option_chain, table='optionchains'):
table=table,
keys=keys_formatted,
values=values_formatted)
#log_msg = "~~~~-----------------~~~"
#print(query)
log_msg = "~~~~-----------------~~~"
query = query.replace("'None'", 'NULL')
if DEBUG is True:
print(query)
cursor.execute(query)
self.connection.commit()
cursor.close()
Expand Down Expand Up @@ -458,5 +471,4 @@ def parse_symbols_and_add_to_db(self):

msg = "Symbols parsed and added to database"
self.log.debug(msg)
print(msg)
return results
96 changes: 51 additions & 45 deletions optionstrader/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,60 +9,66 @@
class Parser:

def __init__(self):
'''
This class is only used for when text needs parsing
'''
return
'''
This class is only used for when text needs parsing
'''
return

def add_stock_to_database(self, symbol):
# DEPRECATED FUNCTION
# This was used to download a list of ticker symbols and current prices.
# Depricated since we are moving foward with tradier, not yahoo as the
# source for the data.
# DEPRECATED FUNCTION
# This was used to download a list of ticker symbols and current prices.
# Depricated since we are moving foward with tradier, not yahoo as the
# source for the data.

webservice = Webservice()
parsed_json = json.loads(webservice.get_from_yahoo(symbol))
dictionary = parsed_json['query']['results']['quote']
webservice = Webservice()
parsed_json = json.loads(webservice.get_from_yahoo(symbol))
dictionary = parsed_json['query']['results']['quote']

database = Database()
database = Database()

column_string = ""
for i in dictionary.items():
column_string = column_string + ", " + i[0]
column_string = ""
for i in dictionary.items():
column_string = column_string + ", " + i[0]

column_string = "(" + column_string[2:] + ")"
column_string = "(" + column_string[2:] + ")"

value_string = ""
for i in dictionary.items():
value_string = value_string + "\", \"" + str(i[1])
value_string = "(\"" + value_string[4:] + "\")"
value_string = ""
for i in dictionary.items():
value_string = value_string + "\", \"" + str(i[1])
value_string = "(\"" + value_string[4:] + "\")"

# Because for some reason there are two "Symbol" fields
column_string = column_string.replace("Symbol", "Symbol_2")
column_string = column_string.replace(", Change, ", ", Change_percent, ")
column_string = column_string.replace(", Name, ", ", Name_of_company, ")
column_string = column_string.replace(", Open, ", ", Open_price, ")
# Because for some reason there are two "Symbol" fields
column_string = column_string.replace("Symbol", "Symbol_2")
column_string = column_string.replace(", Change, ", ", Change_percent, ")
column_string = column_string.replace(", Name, ", ", Name_of_company, ")
column_string = column_string.replace(", Open, ", ", Open_price, ")

database.insert_values_into_table(column_string, value_string)
#print(column_string)
#print(value_string)
database.insert_values_into_table(column_string, value_string)
#print(column_string)
#print(value_string)

database.close_connection()
#print(noob)
print("%s Added to database.") % (symbol)
database.close_connection()
#print(noob)
print("%s Added to database.") % (symbol)

def extract_symbols(self):
file_path = os.path.join(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')), 'nasdaq_symbols.txt')
#file_data = open(file_path, 'r')
with open(file_path, 'r') as file_data:
file_string = file_data.read()
regex = re.compile("^[A-z]{1,}\|.+?\|", re.MULTILINE)
symbols_and_names = re.findall(regex, file_string)

cleaned_symbols_and_names = []
for i in symbols_and_names:
cleaned_symbols_and_names.append(i.split("|")[:-1])

return cleaned_symbols_and_names
#for i in output:
# self.add_stock_to_database(i[:-1])
""" This method sanitizes ticker symbols read from disk.
Returns:
list() of list() of sanitized ticker symbols. Example:
[['T', 'AT&T Inc.'], ['V', 'Visa Inc']]
"""
file_path = os.path.join(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')), 'nasdaq_symbols.txt')
#file_data = open(file_path, 'r')
with open(file_path, 'r') as file_data:
file_string = file_data.read()
regex = re.compile("^[A-z]{1,}\|.+?\|", re.MULTILINE)
symbols_and_names = re.findall(regex, file_string)

cleaned_symbols_and_names = []
for i in symbols_and_names:
cleaned_symbols_and_names.append(i.split("|")[:-1])

return cleaned_symbols_and_names
#for i in output:
# self.add_stock_to_database(i[:-1])
5 changes: 4 additions & 1 deletion optionstrader/scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
from .customlogging import CustomLog
from .analyzer import Analyzer

# Max number of tickers to
MAX_TICKERS_PER_CHUNK = 1000

class Scanner:

def __init__(self):
Expand Down Expand Up @@ -149,7 +152,7 @@ def chunks(self, l, n):

def start_stock_scan(self):
list_of_tickers = self.database.get_list_of_tickers()
for ticker_chunk in self.chunks(list_of_tickers, 1000):
for ticker_chunk in self.chunks(list_of_tickers, MAX_TICKERS_PER_CHUNK):
chunk_stock_data = self.webservice.get_market_quote_for_ticker(self.config.get_environment_url, ticker_chunk)
for single_stock_data in chunk_stock_data:
self.database.save_option_chain_to_table(single_stock_data, table='stocks')
Expand Down
1 change: 1 addition & 0 deletions optionstrader/webservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ def get_example_option_chain(self, environment_url, exp_date):
def get_market_quote_for_ticker(self, environment_url, stock_symbols):
self.session = Tradier(self.access_token)
results = self.session.markets.quotes(stock_symbols)
[print(i) for i in results]
return results

def get_company_information_for_ticker(self, environment_url, stock_symbols):
Expand Down
7 changes: 7 additions & 0 deletions start_scan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import optionstrader
db = optionstrader.Database()
db.configure_database()

scanner = optionstrader.Scanner()
# scanner.start_stock_scan()
scanner.start_option_chain_scan(query_type='default')
9 changes: 5 additions & 4 deletions tests/optionstrader/test_customlogging.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import logging

import unittest
from unittest import mock

from context import CustomLog
from context import optionstrader

class Testcustomlogging(unittest.TestCase):
# Make sure to test all, before a release

def setUp(self):
self.log = CustomLog()
self.log = optionstrader.CustomLog()
return

def tearDown(self):
return

@unittest.skip("PASSED")
def test_log_example(self):
@mock.patch.object(optionstrader, 'CustomLog')
def test_log_example(self, custom_log_mock):
msg = "TESTING..."
#logging.debug(msg)
result = self.log.debug(msg)
Expand Down
Loading

0 comments on commit ed2dbef

Please sign in to comment.