1
0
mirror of https://gitlab.com/simple-stock-bots/simple-stock-bot.git synced 2026-06-03 21:00:26 +00:00

Compare commits

..

9 Commits

Author SHA1 Message Date
Anson 29240b99ac Merge branch 'master' into '88-switch-to-marketdata-app-for-stock-market-data'
# Conflicts:
#   .gitlab-ci.yml
2023-04-07 20:44:47 +00:00
Anson 4abe4fedcc try again 2023-04-07 14:43:43 -06:00
Anson 5b12ed1ce4 small CI change 2023-04-07 14:37:13 -06:00
Anson c6a0320563 round 2 2023-04-07 14:33:27 -06:00
Anson bca9b3e111 time to fight the CI 2023-04-07 14:17:47 -06:00
Anson cedacc5749 small code clean up and add linting to repo 2023-04-07 00:15:01 -06:00
Anson b72f0518c2 get bot working with marketdata api 2023-04-06 23:27:02 -06:00
Anson bc1ad95c75 apply black formatting to previous commit 2023-04-06 17:15:04 -06:00
Anson 7966871869 original progress from a few weekends ago 2023-04-06 16:17:05 -06:00
4 changed files with 26 additions and 39 deletions
+2 -2
View File
@@ -16,7 +16,7 @@ build:master:
--dockerfile "${CI_PROJECT_DIR}/Dockerfile" --dockerfile "${CI_PROJECT_DIR}/Dockerfile"
--destination "${CI_REGISTRY_IMAGE}:latest" --destination "${CI_REGISTRY_IMAGE}:latest"
rules: rules:
- if: '$CI_COMMIT_BRANCH == "master"' - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
build:branch: build:branch:
@@ -31,4 +31,4 @@ build:branch:
--destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA}" --destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA}"
--destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_BRANCH}" --destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_BRANCH}"
rules: rules:
- if: '$CI_COMMIT_BRANCH != "master"' - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME != "master"'
+1 -12
View File
@@ -101,19 +101,8 @@ class MarketData:
""" """
if quoteResp := self.get(f"stocks/quotes/{symbol}/"): if quoteResp := self.get(f"stocks/quotes/{symbol}/"):
price = round(quoteResp["last"][0], 2) return f"The current price of {quoteResp['symbol']} is ${quoteResp['last']}"
changePercent = round(quoteResp["changepct"][0], 2)
message = f"The current price of {symbol.name} is ${price} and "
if changePercent > 0.0:
message += f"is currently up {changePercent}% for the day."
elif changePercent < 0.0:
message += f"is currently down {changePercent}% for the day."
else:
message += "hasn't shown any movement for the day."
return message
else: else:
return f"Getting a quote for {symbol} encountered an error." return f"Getting a quote for {symbol} encountered an error."
+2 -2
View File
@@ -32,8 +32,8 @@ class Stock(Symbol):
def __init__(self, symbol: str) -> None: def __init__(self, symbol: str) -> None:
self.symbol = symbol self.symbol = symbol
self.id = symbol self.id = symbol
self.name = "$" + symbol.upper() self.name = "$" + symbol
self.tag = "$" + symbol.lower() self.tag = "$" + symbol.upper()
class Coin(Symbol): class Coin(Symbol):
+21 -23
View File
@@ -5,7 +5,7 @@ import datetime
import logging import logging
import random import random
import re import re
import logging as log from logging import critical, debug, error, info, warning
import pandas as pd import pandas as pd
import schedule import schedule
@@ -15,13 +15,11 @@ from cg_Crypto import cg_Crypto
from MarketData import MarketData from MarketData import MarketData
from Symbol import Coin, Stock, Symbol from Symbol import Coin, Stock, Symbol
from typing import Dict
class Router: class Router:
STOCK_REGEX = "(?:^|[^\\$])\\$([a-zA-Z.]{1,6})" STOCK_REGEX = "(?:^|[^\\$])\\$([a-zA-Z.]{1,6})"
CRYPTO_REGEX = "[$]{2}([a-zA-Z]{1,20})" CRYPTO_REGEX = "[$]{2}([a-zA-Z]{1,20})"
trending_count: Dict[str, float] = {} trending_count = {}
def __init__(self): def __init__(self):
self.stock = MarketData() self.stock = MarketData()
@@ -45,9 +43,9 @@ class Router:
t_copy.pop(dead) t_copy.pop(dead)
self.trending_count = t_copy.copy() self.trending_count = t_copy.copy()
log.info("Decayed trending symbols.") info("Decayed trending symbols.")
def find_symbols(self, text: str, *, trending_weight: int = 1) -> list[Stock | Symbol]: def find_symbols(self, text: str, *, trending_weight: int = 1) -> list[Symbol]:
"""Finds stock tickers starting with a dollar sign, and cryptocurrencies with two dollar signs """Finds stock tickers starting with a dollar sign, and cryptocurrencies with two dollar signs
in a blob of text and returns them in a list. in a blob of text and returns them in a list.
@@ -63,7 +61,7 @@ class Router:
""" """
schedule.run_pending() schedule.run_pending()
symbols: list[Symbol] = [] symbols = []
stocks = set(re.findall(self.STOCK_REGEX, text)) stocks = set(re.findall(self.STOCK_REGEX, text))
for stock in stocks: for stock in stocks:
# Market data lacks tools to check if a symbol is valid. # Market data lacks tools to check if a symbol is valid.
@@ -72,16 +70,16 @@ class Router:
coins = set(re.findall(self.CRYPTO_REGEX, text)) coins = set(re.findall(self.CRYPTO_REGEX, text))
for coin in coins: for coin in coins:
sym = self.crypto.symbol_list[self.crypto.symbol_list["symbol"].str.fullmatch(coin.lower(), case=False)] sym = self.crypto.symbol_list[self.crypto.symbol_list["symbol"].str.fullmatch(coin.lower(), case=False)]
if sym.empty: if ~sym.empty:
log.info(f"{coin} is not in list of coins")
else:
symbols.append(Coin(sym)) symbols.append(Coin(sym))
else:
info(f"{coin} is not in list of coins")
if symbols: if symbols:
log.info(symbols) info(symbols)
for symbol in symbols: for symbol in symbols:
self.trending_count[symbol.tag] = self.trending_count.get(symbol.tag, 0) + trending_weight self.trending_count[symbol.tag] = self.trending_count.get(symbol.tag, 0) + trending_weight
return symbols return symbols
def status(self, bot_resp) -> str: def status(self, bot_resp) -> str:
"""Checks for any issues with APIs. """Checks for any issues with APIs.
@@ -103,7 +101,7 @@ class Router:
{self.crypto.status()} {self.crypto.status()}
""" """
log.warning(stats) warning(stats)
return stats return stats
@@ -152,13 +150,13 @@ class Router:
replies = [] replies = []
for symbol in symbols: for symbol in symbols:
log.info(symbol) info(symbol)
if isinstance(symbol, Stock): if isinstance(symbol, Stock):
replies.append(self.stock.price_reply(symbol)) replies.append(self.stock.price_reply(symbol))
elif isinstance(symbol, Coin): elif isinstance(symbol, Coin):
replies.append(self.crypto.price_reply(symbol)) replies.append(self.crypto.price_reply(symbol))
else: else:
log.info(f"{symbol} is not a Stock or Coin") info(f"{symbol} is not a Stock or Coin")
return replies return replies
@@ -184,7 +182,7 @@ class Router:
elif isinstance(symbol, Coin): elif isinstance(symbol, Coin):
replies.append(self.crypto.info_reply(symbol)) replies.append(self.crypto.info_reply(symbol))
else: else:
log.debug(f"{symbol} is not a Stock or Coin") debug(f"{symbol} is not a Stock or Coin")
return replies return replies
@@ -208,7 +206,7 @@ class Router:
elif isinstance(symbol, Coin): elif isinstance(symbol, Coin):
return self.crypto.intra_reply(symbol) return self.crypto.intra_reply(symbol)
else: else:
log.debug(f"{symbol} is not a Stock or Coin") debug(f"{symbol} is not a Stock or Coin")
return pd.DataFrame() return pd.DataFrame()
def chart_reply(self, symbol: Symbol) -> pd.DataFrame: def chart_reply(self, symbol: Symbol) -> pd.DataFrame:
@@ -231,7 +229,7 @@ class Router:
elif isinstance(symbol, Coin): elif isinstance(symbol, Coin):
return self.crypto.chart_reply(symbol) return self.crypto.chart_reply(symbol)
else: else:
log.debug(f"{symbol} is not a Stock or Coin") debug(f"{symbol} is not a Stock or Coin")
return pd.DataFrame() return pd.DataFrame()
def stat_reply(self, symbols: list[Symbol]) -> list[str]: def stat_reply(self, symbols: list[Symbol]) -> list[str]:
@@ -256,7 +254,7 @@ class Router:
elif isinstance(symbol, Coin): elif isinstance(symbol, Coin):
replies.append(self.crypto.stat_reply(symbol)) replies.append(self.crypto.stat_reply(symbol))
else: else:
log.debug(f"{symbol} is not a Stock or Coin") debug(f"{symbol} is not a Stock or Coin")
return replies return replies
@@ -282,7 +280,7 @@ class Router:
elif isinstance(symbol, Coin): elif isinstance(symbol, Coin):
replies.append(self.crypto.cap_reply(symbol)) replies.append(self.crypto.cap_reply(symbol))
else: else:
log.debug(f"{symbol} is not a Stock or Coin") debug(f"{symbol} is not a Stock or Coin")
return replies return replies
@@ -308,7 +306,7 @@ class Router:
elif isinstance(symbol, Coin): elif isinstance(symbol, Coin):
replies.append(self.crypto.spark_reply(symbol)) replies.append(self.crypto.spark_reply(symbol))
else: else:
log.debug(f"{symbol} is not a Stock or Coin") debug(f"{symbol} is not a Stock or Coin")
return replies return replies
@@ -354,7 +352,7 @@ class Router:
if reply: if reply:
return reply return reply
else: else:
log.warning("Failed to collect trending data.") warning("Failed to collect trending data.")
return "Trending data is not currently available." return "Trending data is not currently available."
def random_pick(self) -> str: def random_pick(self) -> str:
@@ -387,7 +385,7 @@ class Router:
elif isinstance(symbol, Coin): elif isinstance(symbol, Coin):
coins.append(symbol) coins.append(symbol)
else: else:
log.debug(f"{symbol} is not a Stock or Coin") debug(f"{symbol} is not a Stock or Coin")
if stocks: if stocks:
# IEX batch endpoint doesnt seem to be working right now # IEX batch endpoint doesnt seem to be working right now