- Added delete command

- added watchlists
- added $pf2 and $wl2 to get image format table outputs
- moving yahoo finance commands to separate file
This commit is contained in:
socks 2021-02-14 18:57:18 +00:00
parent f3a622b95f
commit 35fc806327
9 changed files with 265 additions and 60 deletions

View file

@ -1,35 +0,0 @@
import json
import asyncio
from config import config
db = config['database']
def write_file(data):
with open(db, 'w') as f:
f.write(data)
def get_stocks(user):
with open(db) as f:
data = json.loads(f.read())
if user in data.keys():
user_data = data[user]
return user_data['portfolio']
else:
data[user] = {"portfolio": {}}
write_file(json.dumps(data))
return get_stocks(user)
def add_stock(user, stock, amount):
with open(db) as f:
data = json.loads(f.read())
if user in data.keys():
print(data.keys())
if stock in data[user]['portfolio'].keys():
data[user]['portfolio'][stock] += amount
else:
data[user]['portfolio'][stock] = amount
write_file(json.dumps(data))
return True
else:
get_stocks(user)
return add_stock(user, stock, amount)

View file

@ -1 +0,0 @@
socks@meme-machine.555521:1612898779

View file

@ -21,13 +21,11 @@ def get_stocks(user):
data = json.loads(f.read()) data = json.loads(f.read())
data = dict(data) data = dict(data)
print("USER" + str(user))
if user in list(data.keys()): if user in list(data.keys()):
user_data = data[user] user_data = data[user]
return user_data['portfolio'] return user_data['portfolio']
else: else:
print(data) data[user] = {"portfolio": {}, "watchlist": {}}
data[user] = {"portfolio": {}}
write_file(json.dumps(data)) write_file(json.dumps(data))
return get_stocks(user) return get_stocks(user)
@ -35,8 +33,6 @@ def add_stock(user, stock, amount):
with open(db) as f: with open(db) as f:
data = dict(json.loads(f.read())) data = dict(json.loads(f.read()))
print(data)
print(type(data))
if user in data.keys(): if user in data.keys():
if stock in data[user]['portfolio'].keys(): if stock in data[user]['portfolio'].keys():
data[user]['portfolio'][stock] = str(Decimal(amount) + Decimal( data[user]['portfolio'][stock] )) data[user]['portfolio'][stock] = str(Decimal(amount) + Decimal( data[user]['portfolio'][stock] ))
@ -48,3 +44,63 @@ def add_stock(user, stock, amount):
else: else:
get_stocks(user) get_stocks(user)
return add_stock(user, stock, amount) return add_stock(user, stock, amount)
def delete_stock(user, stock):
with open(db) as f:
data = json.loads(f.read())
if user in data.keys():
# user exists
portfolio = data[user]['portfolio']
if stock in portfolio.keys():
# stock exists
del portfolio[stock]
data[user]['portfolio'] = portfolio
write_file(json.dumps(data))
return get_stocks(user)
def get_watchlist(user):
with open(db) as f:
data = json.loads(f.read())
if user not in data.keys():
get_stocks(user)
get_watchlist(user)
return data[user]['watchlist']
def watch(user, stock, est_price=0):
with open(db) as f:
data = json.loads(f.read())
if user not in data.keys():
get_stocks(user)
add_to_watchlist(user, list_name, stock)
if not stock_exists(stock):
return False
watchlist = data[user]['watchlist']
watchlist[stock] = str(Decimal(est_price))
data[user]['watchlist'] = watchlist
write_file(json.dumps(data))
return True
def unwatch(user, stock):
with open(db) as f:
data = json.loads(f.read())
if user not in data.keys():
get_stocks(user)
return
if not stock_exists: return
watchlist = data[user]['watchlist']
del watchlist[stock]
data[user]['watchlist'] = watchlist
write_file(json.dumps(data))

104
main.py
View file

@ -1,7 +1,10 @@
import discord import discord
import database, table import database, table, yfi
import table2 as t2
from discord.ext import commands from discord.ext import commands
from config import config from config import config
from decimal import Decimal
import typing
intents = discord.Intents.default() intents = discord.Intents.default()
@ -16,22 +19,119 @@ async def ping(ctx):
await ctx.send("pong!") await ctx.send("pong!")
@bot.command(aliases=['pf'])
async def portfolio(ctx):
user = str(ctx.message.author)
return await ctx.send(str( "```" + table.generate_table(database.get_stocks(user)) + "```" ))
@bot.command()
async def pf2(ctx):
user = str(ctx.message.author)
portfolio = database.get_stocks(user)
data = []
for stock in portfolio.keys():
data.append([
stock,
Decimal(portfolio[stock]),
round(float(Decimal(portfolio[stock]) * Decimal(yfi.get_current_price(stock))), 2)
])
data.append(["Total", "", round( sum([x[2] for x in data]), 2) ] )
image = t2.generate_table(
headers = ["Ticker", "Shares", "Value ($)"],
data = data,
title = str(user + "'s Portfolio")
)
await ctx.send(file=discord.File(image, 'table.png'))
image.close()
@bot.command() @bot.command()
async def add(ctx, stock, amount): async def add(ctx, stock, amount):
user = str(ctx.message.author)
stock = stock.upper()
try: try:
float(amount) float(amount)
except ValueError: except ValueError:
await ctx.send("amoutn not a number") await ctx.send("amoutn not a number")
return return
user = str(ctx.message.author)
if database.add_stock(user, stock, amount): if database.add_stock(user, stock, amount):
return await ctx.send(str( "```" + table.generate_table(database.get_stocks(user)) + "```" )) return await ctx.send(str( "```" + table.generate_table(database.get_stocks(user)) + "```" ))
else: else:
return await ctx.send("Stock **{0}** does not exist!".format(stock)) return await ctx.send("Stock **{0}** does not exist!".format(stock))
@bot.command(aliases=['del'])
async def delete(ctx, stock):
stock = stock.upper()
user = str(ctx.message.author)
return await ctx.send(str( "```" + table.generate_table(database.delete_stock(user, stock)) + "```" ))
@bot.command(aliases=['wl'])
async def watchlist(ctx):
user = str(ctx.message.author)
wlist = database.get_watchlist(user)
return await ctx.send( str ( "```" + table.watchlist_table(wlist) + "```") )
@bot.command(aliases=['w'])
async def watch(ctx, stock, est_price: typing.Optional[int]):
if not est_price:
est_price = 0
user = str(ctx.message.author)
stock = stock.upper()
try:
float(est_price)
except ValueError:
await ctx.send("Estimated price not a number")
return
if database.watch(user, stock, est_price):
return await ctx.send("Updated watchlist")
else:
return await ctx.send("Stock **{0}** does not exist!".format(stock))
@bot.command(aliases=['uw'])
async def unwatch(ctx, stock):
user = str(ctx.message.author)
stock = stock.upper()
database.unwatch(user, stock)
return await ctx.send("Updated watchlist")
@bot.command()
async def wl2(ctx, user: typing.Optional[discord.Member]):
if not user:
user = str(ctx.message.author)
else:
print(str(user))
user = str(user)
watchlist = database.get_watchlist(user)
data = []
for stock in watchlist.keys():
data.append([
stock,
yfi.get_current_price(stock),
Decimal(watchlist[stock]),
])
image = t2.generate_table(
headers = ["Ticker", "Value ($)", "Est. Price ($)"],
data = data,
title = str(user + "'s Watchlist"),
bg = 'lightgreen', border='limegreen'
)
await ctx.send(file=discord.File(image, 'table.png'))
image.close()
bot.run(config['apikey']) bot.run(config['apikey'])

View file

@ -1 +1 @@
{"Katte#3575": {"portfolio": {"AAPL": "0.37795852", "GME": "6.43", "AMD": "0.2661378", "AMZN": "0.00534034", "ETH-USD": "0.02", "HMMJ.TO": "14.14"}}, "Haedrien#6134": {"portfolio": {"UAMY": "150", "GME": "92.922", "ZOM": "100", "otlk": "100", "zsan": "100", "CTRM": "13.48"}}, "Forchex#1473": {"portfolio": {"AMC": "12", "GME": "19.7", "TGB": "56.52"}}, "Stonks#4179": {"portfolio": {"TANH": "100", "MICT": "100", "CEPU": "100", "NEXT": "100", "FTK": "100", "AVCO": "100", "CJJD": "100"}}} {"Katte#3575": {"portfolio": {"AAPL": "0.37795852", "GME": "6.43", "AMD": "0.2661378", "AMZN": "0.00534034", "ETH-USD": "0.02", "HMMJ.TO": "14.14", "BTC-USD": "0.00038396"}, "watchlist": {"AAPL": "150", "GME": "0", "AMD": "0", "AMZN": "0"}}, "Haedrien#6134": {"portfolio": {"UAMY": "150", "GME": "92.922", "ZOM": "100", "otlk": "100", "zsan": "100", "CTRM": "13.48"}, "watchlist": {}}, "Forchex#1473": {"portfolio": {"AMC": "12", "GME": "19.7", "TGB": "56.52"}, "watchlist": {}}, "Stonks#4179": {"portfolio": {"TANH": "100", "MICT": "100", "CEPU": "100", "NEXT": "100", "FTK": "100", "AVCO": "100", "CJJD": "100", "GLDG": "100", "ORLA": "100"}, "watchlist": {}}}

BIN
table.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View file

@ -1,26 +1,12 @@
from tabulate import tabulate from tabulate import tabulate
from decimal import Decimal from decimal import Decimal
import yfinance as yf import yfi as y
def get_current_price(ticker):
yf_obj = yf.Ticker(ticker)
todays_data = yf_obj.history(period='1d')
return round(todays_data['Close'][0], 2)
stonks = {
'MSFT': 4.3,
'AAPL': 13,
'GME' : 212
}
def generate_table(stonks): def generate_table(stonks):
table_data = [] table_data = []
total = 0 total = 0
for ticker in stonks.keys(): for ticker in stonks.keys():
price = get_current_price(ticker) price = y.get_current_price(ticker)
shares_count = stonks[ticker] shares_count = stonks[ticker]
table_data.append([ticker, shares_count, round(Decimal(price) * Decimal(stonks[ticker]), 2)]) table_data.append([ticker, shares_count, round(Decimal(price) * Decimal(stonks[ticker]), 2)])
total += (Decimal(price) * Decimal(stonks[ticker])) total += (Decimal(price) * Decimal(stonks[ticker]))
@ -28,3 +14,18 @@ def generate_table(stonks):
table_data.append(['Total', '', round(total, 2)]) table_data.append(['Total', '', round(total, 2)])
return str( tabulate(table_data, ['Ticker', 'Shares', 'Value ($)'], tablefmt="pretty") ) return str( tabulate(table_data, ['Ticker', 'Shares', 'Value ($)'], tablefmt="pretty") )
def watchlist_table(watchlist):
table_data = []
header = ['Ticker', 'Current Price ($)', 'Estimated Price ($)']
for stonk in watchlist.keys():
table_data.append([
stonk,
y.get_current_price(stonk),
watchlist[stonk],
])
return str( tabulate( table_data, header, tablefmt="pretty" ) )

76
table2.py Normal file
View file

@ -0,0 +1,76 @@
import matplotlib.pyplot as plt
import matplotlib, io
from datetime import datetime
def generate_table(headers, data, title="", bg='skyblue', border='steelblue'):
timestamp = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
font = {'family' : 'monospace',
'weight' : 'normal',
'size' : 12}
matplotlib.rc('font', **font)
title_text = title
footer_text = timestamp
fig_background_color = bg
fig_border = border
column_headers = headers
if data:
cell_text = []
for row in data:
cell_text.append([x for x in row])
else:
cell_text = [["No Data"] + ["" for x in range(len(headers)-1)]]
# Create the figure. Setting a small pad on tight_layout
# seems to better regulate white space. Sometimes experimenting
# with an explicit figsize here can produce better outcome.
image_height = (( 0.9375 + ( 0.40625 * ( len(data) + 1) ) ) * 160)
image_width = 6 * 160
plt.figure(linewidth=2,
edgecolor=fig_border,
facecolor=fig_background_color,
tight_layout={'pad':1},
dpi=160,
figsize=(image_width/160, image_height/160)
)
# Add a table at the bottom of the axes
the_table = plt.table(cellText=cell_text,
colLabels=column_headers,
loc='center')# Scaling is the only influence we have over top and bottom cell padding.
# Make the rows taller (i.e., make cell y scale larger).
the_table.scale(1, 2)
# Hide axes
ax = plt.gca()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
# Hide axes border
plt.box(on=None)
# Add title
plt.suptitle(title_text)
# Add footer
plt.figtext(((image_width - 15)/image_width), 1-((image_height - 15)/image_height), footer_text, horizontalalignment='right', size=12, weight='light')
# Force the figure to update, so backends center objects correctly within the figure.
# Without plt.draw() here, the title will center on the axes and not the figure.
plt.draw()
# Create image. plt.savefig ignores figure edge and face colors, so map them.
image_buffer = io.BytesIO()
plt.savefig(image_buffer, format='png')
image_buffer.seek(0)
return image_buffer

8
yfi.py Normal file
View file

@ -0,0 +1,8 @@
import yfinance as yf
def get_current_price(ticker):
yf_obj = yf.Ticker(ticker)
todays_data = yf_obj.history(period='1d')
return round(todays_data['Close'][0], 2)