- 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:
parent
f3a622b95f
commit
35fc806327
9 changed files with 265 additions and 60 deletions
|
@ -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)
|
|
@ -1 +0,0 @@
|
|||
socks@meme-machine.555521:1612898779
|
66
database.py
66
database.py
|
@ -21,13 +21,11 @@ def get_stocks(user):
|
|||
data = json.loads(f.read())
|
||||
|
||||
data = dict(data)
|
||||
print("USER" + str(user))
|
||||
if user in list(data.keys()):
|
||||
user_data = data[user]
|
||||
return user_data['portfolio']
|
||||
else:
|
||||
print(data)
|
||||
data[user] = {"portfolio": {}}
|
||||
data[user] = {"portfolio": {}, "watchlist": {}}
|
||||
write_file(json.dumps(data))
|
||||
return get_stocks(user)
|
||||
|
||||
|
@ -35,8 +33,6 @@ def add_stock(user, stock, amount):
|
|||
|
||||
with open(db) as f:
|
||||
data = dict(json.loads(f.read()))
|
||||
print(data)
|
||||
print(type(data))
|
||||
if user in data.keys():
|
||||
if stock in data[user]['portfolio'].keys():
|
||||
data[user]['portfolio'][stock] = str(Decimal(amount) + Decimal( data[user]['portfolio'][stock] ))
|
||||
|
@ -48,3 +44,63 @@ def add_stock(user, stock, amount):
|
|||
else:
|
||||
get_stocks(user)
|
||||
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
104
main.py
|
@ -1,7 +1,10 @@
|
|||
import discord
|
||||
import database, table
|
||||
import database, table, yfi
|
||||
import table2 as t2
|
||||
from discord.ext import commands
|
||||
from config import config
|
||||
from decimal import Decimal
|
||||
import typing
|
||||
|
||||
intents = discord.Intents.default()
|
||||
|
||||
|
@ -16,22 +19,119 @@ async def ping(ctx):
|
|||
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()
|
||||
async def add(ctx, stock, amount):
|
||||
user = str(ctx.message.author)
|
||||
stock = stock.upper()
|
||||
try:
|
||||
float(amount)
|
||||
except ValueError:
|
||||
await ctx.send("amoutn not a number")
|
||||
return
|
||||
|
||||
user = str(ctx.message.author)
|
||||
if database.add_stock(user, stock, amount):
|
||||
return await ctx.send(str( "```" + table.generate_table(database.get_stocks(user)) + "```" ))
|
||||
else:
|
||||
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'])
|
||||
|
|
|
@ -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
BIN
table.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 56 KiB |
33
table.py
33
table.py
|
@ -1,26 +1,12 @@
|
|||
from tabulate import tabulate
|
||||
from decimal import Decimal
|
||||
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)
|
||||
|
||||
|
||||
stonks = {
|
||||
'MSFT': 4.3,
|
||||
'AAPL': 13,
|
||||
'GME' : 212
|
||||
}
|
||||
|
||||
import yfi as y
|
||||
|
||||
def generate_table(stonks):
|
||||
table_data = []
|
||||
total = 0
|
||||
for ticker in stonks.keys():
|
||||
price = get_current_price(ticker)
|
||||
price = y.get_current_price(ticker)
|
||||
shares_count = stonks[ticker]
|
||||
table_data.append([ticker, shares_count, round(Decimal(price) * Decimal(stonks[ticker]), 2)])
|
||||
total += (Decimal(price) * Decimal(stonks[ticker]))
|
||||
|
@ -28,3 +14,18 @@ def generate_table(stonks):
|
|||
table_data.append(['Total', '', round(total, 2)])
|
||||
|
||||
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
76
table2.py
Normal 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
8
yfi.py
Normal 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)
|
||||
|
||||
|
Loading…
Add table
Reference in a new issue