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 | Date | |
|---|---|---|---|
| 29240b99ac | |||
| 4abe4fedcc | |||
| 5b12ed1ce4 | |||
| c6a0320563 | |||
| bca9b3e111 | |||
| cedacc5749 | |||
| b72f0518c2 | |||
| bc1ad95c75 | |||
| 7966871869 |
+2
-2
@@ -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
@@ -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."
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user