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 27 additions and 60 deletions
+2 -2
View File
@@ -16,7 +16,7 @@ build:master:
--dockerfile "${CI_PROJECT_DIR}/Dockerfile"
--destination "${CI_REGISTRY_IMAGE}:latest"
rules:
- if: '$CI_COMMIT_BRANCH == "master"'
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
build:branch:
@@ -31,4 +31,4 @@ build:branch:
--destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA}"
--destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_BRANCH}"
rules:
- if: '$CI_COMMIT_BRANCH != "master"'
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME != "master"'
+2 -33
View File
@@ -85,27 +85,7 @@ class MarketData:
self.charts = {}
def status(self) -> str:
# TODO: At the moment this API is poorly documented, this function likely needs to be revisited later.
try:
status = r.get(
"https://stats.uptimerobot.com/api/getMonitorList/6Kv3zIow0A",
timeout=5,
)
status.raise_for_status()
except r.HTTPError:
return f"API returned an HTTP error code {status.status_code} in {status.elapsed.total_seconds()} Seconds."
except r.Timeout:
return "API timed out before it was able to give status. This is likely due to a surge in usage or a complete outage."
statusJSON = status.json()
if statusJSON["status"] == "ok":
return (
f"CoinGecko API responded that it was OK with a {status.status_code} in {status.elapsed.total_seconds()} Seconds."
)
else:
return f"MarketData.app is currently reporting the following status: {statusJSON['status']}"
return "status isnt implemented by marketdata.app"
def price_reply(self, symbol: Stock) -> str:
"""Returns price movement of Stock for the last market day, or after hours.
@@ -121,19 +101,8 @@ class MarketData:
"""
if quoteResp := self.get(f"stocks/quotes/{symbol}/"):
price = round(quoteResp["last"][0], 2)
changePercent = round(quoteResp["changepct"][0], 2)
return f"The current price of {quoteResp['symbol']} is ${quoteResp['last']}"
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:
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:
self.symbol = symbol
self.id = symbol
self.name = "$" + symbol.upper()
self.tag = "$" + symbol.lower()
self.name = "$" + symbol
self.tag = "$" + symbol.upper()
class Coin(Symbol):
+20 -22
View File
@@ -5,7 +5,7 @@ import datetime
import logging
import random
import re
import logging as log
from logging import critical, debug, error, info, warning
import pandas as pd
import schedule
@@ -15,13 +15,11 @@ from cg_Crypto import cg_Crypto
from MarketData import MarketData
from Symbol import Coin, Stock, Symbol
from typing import Dict
class Router:
STOCK_REGEX = "(?:^|[^\\$])\\$([a-zA-Z.]{1,6})"
CRYPTO_REGEX = "[$]{2}([a-zA-Z]{1,20})"
trending_count: Dict[str, float] = {}
trending_count = {}
def __init__(self):
self.stock = MarketData()
@@ -45,9 +43,9 @@ class Router:
t_copy.pop(dead)
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
in a blob of text and returns them in a list.
@@ -63,7 +61,7 @@ class Router:
"""
schedule.run_pending()
symbols: list[Symbol] = []
symbols = []
stocks = set(re.findall(self.STOCK_REGEX, text))
for stock in stocks:
# Market data lacks tools to check if a symbol is valid.
@@ -72,12 +70,12 @@ class Router:
coins = set(re.findall(self.CRYPTO_REGEX, text))
for coin in coins:
sym = self.crypto.symbol_list[self.crypto.symbol_list["symbol"].str.fullmatch(coin.lower(), case=False)]
if sym.empty:
log.info(f"{coin} is not in list of coins")
else:
if ~sym.empty:
symbols.append(Coin(sym))
else:
info(f"{coin} is not in list of coins")
if symbols:
log.info(symbols)
info(symbols)
for symbol in symbols:
self.trending_count[symbol.tag] = self.trending_count.get(symbol.tag, 0) + trending_weight
@@ -103,7 +101,7 @@ class Router:
{self.crypto.status()}
"""
log.warning(stats)
warning(stats)
return stats
@@ -152,13 +150,13 @@ class Router:
replies = []
for symbol in symbols:
log.info(symbol)
info(symbol)
if isinstance(symbol, Stock):
replies.append(self.stock.price_reply(symbol))
elif isinstance(symbol, Coin):
replies.append(self.crypto.price_reply(symbol))
else:
log.info(f"{symbol} is not a Stock or Coin")
info(f"{symbol} is not a Stock or Coin")
return replies
@@ -184,7 +182,7 @@ class Router:
elif isinstance(symbol, Coin):
replies.append(self.crypto.info_reply(symbol))
else:
log.debug(f"{symbol} is not a Stock or Coin")
debug(f"{symbol} is not a Stock or Coin")
return replies
@@ -208,7 +206,7 @@ class Router:
elif isinstance(symbol, Coin):
return self.crypto.intra_reply(symbol)
else:
log.debug(f"{symbol} is not a Stock or Coin")
debug(f"{symbol} is not a Stock or Coin")
return pd.DataFrame()
def chart_reply(self, symbol: Symbol) -> pd.DataFrame:
@@ -231,7 +229,7 @@ class Router:
elif isinstance(symbol, Coin):
return self.crypto.chart_reply(symbol)
else:
log.debug(f"{symbol} is not a Stock or Coin")
debug(f"{symbol} is not a Stock or Coin")
return pd.DataFrame()
def stat_reply(self, symbols: list[Symbol]) -> list[str]:
@@ -256,7 +254,7 @@ class Router:
elif isinstance(symbol, Coin):
replies.append(self.crypto.stat_reply(symbol))
else:
log.debug(f"{symbol} is not a Stock or Coin")
debug(f"{symbol} is not a Stock or Coin")
return replies
@@ -282,7 +280,7 @@ class Router:
elif isinstance(symbol, Coin):
replies.append(self.crypto.cap_reply(symbol))
else:
log.debug(f"{symbol} is not a Stock or Coin")
debug(f"{symbol} is not a Stock or Coin")
return replies
@@ -308,7 +306,7 @@ class Router:
elif isinstance(symbol, Coin):
replies.append(self.crypto.spark_reply(symbol))
else:
log.debug(f"{symbol} is not a Stock or Coin")
debug(f"{symbol} is not a Stock or Coin")
return replies
@@ -354,7 +352,7 @@ class Router:
if reply:
return reply
else:
log.warning("Failed to collect trending data.")
warning("Failed to collect trending data.")
return "Trending data is not currently available."
def random_pick(self) -> str:
@@ -387,7 +385,7 @@ class Router:
elif isinstance(symbol, Coin):
coins.append(symbol)
else:
log.debug(f"{symbol} is not a Stock or Coin")
debug(f"{symbol} is not a Stock or Coin")
if stocks:
# IEX batch endpoint doesnt seem to be working right now