Skip to content

Commit f81dff9

Browse files
author
investingbots
authored
Merge pull request #3 from investingbots/develop
Develop initial setup
2 parents 276a758 + 828be0b commit f81dff9

File tree

7 files changed

+196
-65
lines changed

7 files changed

+196
-65
lines changed

bot/bot.py

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
from typing import Any, Dict
44

5+
from bot.data import remove_ticker, get_tickers, add_ticker, get_company_profile
56
from bot import __version__, OperationalException
67
from bot.data.data_provider_manager import DataProviderManager
7-
from bot.data.data_providers import DataProviderException
88

99
logger = logging.getLogger(__name__)
1010

@@ -14,25 +14,86 @@ class Bot:
1414
def __init__(self, config: Dict[str, Any]) -> None:
1515
logger.info('Starting bot version %s', __version__)
1616

17-
# Init objects
18-
19-
# Make variable private, only bot should change them
17+
# Make variables private, only bot should change them
2018
self.__config = config
2119
self.__data_provider_manager = DataProviderManager(self.config)
2220

21+
# Load tickers
22+
self._load_tickers()
23+
2324
@property
2425
def config(self) -> Dict[str, Any]:
2526
return self.__config
2627

2728
def set_config(self, config: Dict[str, Any]):
2829
self.__config = config
2930

31+
def _load_tickers(self):
32+
logger.info("Initializing provided tickers from config ...")
33+
tickers = self.__config.get('tickers', [])
34+
35+
for ticker in tickers:
36+
37+
try:
38+
self.add_ticker(ticker)
39+
except OperationalException as e:
40+
logger.error(str(e))
41+
continue
42+
3043
def add_ticker(self, ticker: str) -> None:
44+
logger.info("Adding ticker ...")
45+
46+
if not get_company_profile(ticker, self.config):
47+
48+
if self.__data_provider_manager.evaluate_ticker(ticker):
49+
50+
profile = self.__data_provider_manager.get_profile(ticker)
51+
52+
if not profile:
53+
raise OperationalException("Could not evaluate {} with the data providers".format(ticker))
54+
55+
company_name = profile.get('profile', {}).get('companyName', None)
56+
category = profile.get('profile', {}).get('industry', None)
57+
58+
if not company_name:
59+
raise OperationalException("Could not evaluate company name for ticker {} with the data providers")
60+
61+
if not company_name:
62+
raise OperationalException("Could not evaluate category for ticker {} with the data providers")
63+
64+
try:
65+
add_ticker(
66+
ticker,
67+
company_name=company_name,
68+
category=category,
69+
config=self.config
70+
)
71+
except Exception:
72+
raise OperationalException(
73+
"Something went wrong with adding ticker {} to the registry".format(ticker)
74+
)
75+
else:
76+
raise OperationalException("Could not evaluate ticker {} with the data providers".format(ticker))
77+
else:
78+
raise OperationalException(
79+
"Ticker {} is already present in registry".format(ticker)
80+
)
81+
82+
def remove_ticker(self, ticker: str) -> None:
83+
logger.info("Removing ticker ...")
84+
85+
if get_company_profile(ticker, self.config):
86+
87+
try:
88+
remove_ticker(ticker, self.config)
89+
except Exception:
90+
raise OperationalException("Something went wrong while deleting the ticker from the registry")
91+
else:
92+
raise OperationalException("Provided ticker {} does not exist".format(ticker))
3193

32-
try:
33-
self.__data_provider_manager.add_ticker(ticker)
34-
except DataProviderException as e:
35-
raise OperationalException(str(e))
94+
def list_tickers(self):
95+
logger.info("Listing tickers ...")
96+
return get_tickers(self.config)
3697

3798

3899

bot/data/__init__.py

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import logging
22
import sqlite3
3-
from typing import Dict, Any, List
3+
from typing import Dict, Any, List, Tuple
44

55
from bot import setup
66

@@ -31,7 +31,7 @@ def create_tables(config: Dict[str, Any]) -> None:
3131
con.close()
3232

3333
if TRADES_TABLE_NAME not in table_names:
34-
logger.info("Creating database table {}...".format(TRADES_TABLE_NAME))
34+
logger.info("Creating database table {} ...".format(TRADES_TABLE_NAME))
3535
con = create_connection(config)
3636

3737
# Create open trades table
@@ -45,42 +45,65 @@ def create_tables(config: Dict[str, Any]) -> None:
4545

4646

4747
def add_ticker(ticker: str, company_name: str, category: str, config: Dict[str, Any]) -> None:
48+
49+
logger.info("Adding ticker {} to registry...".format(ticker))
50+
4851
con = create_connection(config)
4952
cursor = con.cursor()
5053

51-
logger.info("Adding ticker {} ...".format(ticker))
54+
# Add ticker if not exists
55+
insert_statement = """
56+
INSERT INTO TICKERS (ticker, company_name, category)
57+
VALUES (?, ?, ?);
58+
"""
5259

53-
# Get ticker if exists
54-
select_statement = """SELECT ticker_id from TICKERS where ticker = ?"""
55-
cursor.execute(select_statement, (ticker,))
60+
data_tuple = (ticker, company_name, category)
61+
cursor.execute(insert_statement, data_tuple)
5662

57-
result = cursor.fetchall()
63+
con.commit()
64+
con.close()
5865

59-
if result:
60-
logger.info("Ticker already in database")
61-
else:
62-
# Add ticker if not exists
63-
insert_statement = """
64-
INSERT INTO TICKERS (ticker, company_name, category)
65-
VALUES (?, ?, ?);
66-
"""
6766

68-
data_tuple = (ticker, company_name, category)
69-
cursor.execute(insert_statement, data_tuple)
67+
def remove_ticker(ticker: str, config: Dict[str, Any]) -> None:
7068

69+
logger.info("Removing ticker {} from registry ...".format(ticker))
70+
con = create_connection(config)
71+
cursor = con.cursor()
72+
73+
delete_statement = '''
74+
DELETE from TICKERS where ticker = ?
75+
'''
76+
77+
cursor.execute(delete_statement, (ticker,))
7178
con.commit()
7279
con.close()
7380

7481

75-
def get_company_info(ticker: str, config: Dict[str, any]) -> List[str]:
82+
def get_company_profile(ticker: str, config: Dict[str, any]) -> Tuple[str]:
7683
con = create_connection(config)
7784
cursor = con.cursor()
7885

79-
logger.info("Getting {} company info ...".format(ticker))
86+
logger.info("Getting {} company info from registry ...".format(ticker))
87+
88+
cursor.execute(" SELECT * FROM TICKERS WHERE ticker=?", (ticker, ))
89+
result = cursor.fetchall()
90+
91+
con.close()
92+
return result
93+
94+
95+
def get_tickers(config: Dict[str, any]) -> List[str]:
96+
con = create_connection(config)
97+
cursor = con.cursor()
98+
99+
logger.info("Getting all tickers from registry ...")
80100

81101
# Get ticker if exists
82-
select_statement = """SELECT ticker_id from TICKERS where ticker = ?"""
83-
cursor.execute(select_statement, (ticker,))
102+
select_statement = '''
103+
SELECT (ticker) from TICKERS
104+
'''
105+
106+
cursor.execute(select_statement)
84107
result = cursor.fetchall()
85108
con.close()
86109
return result

bot/data/data_provider_manager.py

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from typing import List, Dict, Any
33

44
from bot.data.data_providers import DataProvider, DataProviderException
5-
from . import add_ticker, get_all_table_names, create_tables, get_company_info
5+
from . import get_all_table_names, create_tables
66

77
logger = logging.getLogger(__name__)
88

@@ -29,24 +29,23 @@ def __init__(self, config: Dict[str, Any]) -> None:
2929
from bot.data.data_providers.fmp_data_provider import FMPDataProvider
3030
self.registered_modules.append(FMPDataProvider(self.__config))
3131

32-
def add_ticker(self, ticker: str) -> None:
32+
def evaluate_ticker(self, ticker: str) -> bool:
3333

34-
if get_company_info(ticker, self.__config):
35-
raise DataProviderException("Ticker {} already exists".format(ticker))
36-
else:
37-
for data_provider in self.registered_modules:
34+
for data_provider in self.registered_modules:
3835

39-
if data_provider.evaluate_ticker(ticker):
40-
logger.info("Ticker exists")
41-
profile = data_provider.get_profile(ticker)
36+
if data_provider.evaluate_ticker(ticker):
37+
logger.info("Ticker exists")
38+
return True
4239

43-
company_name = profile.get('profile', {}).get('companyName', {})
44-
industry = profile.get('profile', {}).get('industry', {})
40+
return False
4541

46-
if company_name and industry:
47-
add_ticker(ticker, company_name, industry, self.__config)
48-
logger.info("Ticker {} has been added ...".format(ticker))
49-
return
42+
def get_profile(self, ticker: str) -> Dict:
5043

51-
raise DataProviderException("Could not evaluate ticker {}".format(ticker))
44+
for data_provider in self.registered_modules:
5245

46+
profile = data_provider.get_profile(ticker)
47+
48+
if profile:
49+
return profile
50+
51+
raise DataProviderException("Could not profile for {}".format(ticker))

bot/data/data_providers/fmp_data_provider.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1+
import logging
12
import json
2-
from enum import Enum
33
from typing import Dict, Any
44

55
from urllib.request import urlopen
6+
from urllib import error
67

78
from bot.data.data_providers.data_provider import DataProvider, DataProviderException
89

910
PROFILE_ENDPOINT = 'https://financialmodelingprep.com/api/v3/company/profile/{}'
1011

12+
logger = logging.getLogger(__name__)
13+
1114

1215
class FMPDataProvider(DataProvider):
1316

@@ -24,15 +27,14 @@ def get_data(self, ticker: str = None):
2427
pass
2528

2629
def evaluate_ticker(self, ticker: str) -> bool:
27-
2830
try:
2931
url = PROFILE_ENDPOINT.format(ticker)
30-
3132
response = urlopen(url)
3233
data = response.read().decode("utf-8")
3334
data = json.loads(data)
34-
3535
return data['symbol'] == ticker
36+
except error.HTTPError:
37+
return False
3638
except Exception:
3739
return False
3840

@@ -44,5 +46,3 @@ def get_profile(self, ticker: str) -> Dict:
4446

4547

4648

47-
48-

bot/services/service.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,6 @@ def cleanup(self) -> None:
4848

4949
def _add_ticker(self, ticker: str) -> None:
5050
self._bot.add_ticker(ticker)
51+
52+
def _remove_ticker(self, ticker: str) -> None:
53+
self._bot.remove_ticker(ticker)

0 commit comments

Comments
 (0)