def record_position(self, position=1): app = db.get_app() pos = Position() pos.position = position pos.week = current_round() pos.season = app.config['SEASON'] self.positions.append(pos)
async def __run_buy(self): user = User.get_by_discord_id(self.message.author.id) order_dict = { 'operation': "buy", 'season': app.config['SEASON'], 'week': current_round() } if user is None: await self.reply([ (f"User {self.message.author.mention} does not exist." "Use !newuser to create user first.") ]) return if len(self.args) not in [2, 3]: await self.reply([ "Incorrect number of arguments!!!", self.__class__.buy_help() ]) return try: stock = Stock.find_by_code(self.args[1]) except MultipleResultsFound as exc: await self.reply([ f"Stock code **{self.args[1]}** is not unique!!!", ]) return if not stock: await self.reply([f"Stock code **{self.args[1]}** not found!"]) return if len(self.args) == 3: if not represents_int(self.args[2]) or (represents_int( self.args[2]) and not int(self.args[2]) > 0): await self.reply( [f"**{self.args[2]}** must be whole positive number!"]) return else: if int(self.args[2]) <= app.config['MAX_SHARE_UNITS']: order_dict['buy_shares'] = self.args[2] else: order_dict['buy_funds'] = self.args[2] round_n = app.config['ROUNDS_COLLECT'][-1] match = MatchService.get_game(stock.name, round_n=round_n) if match and (match.homeTeamName.strip() in app.config['ADMIN_TEAMS'] or \ match.awayTeamName.strip() in app.config['ADMIN_TEAMS']): await self.reply( [f"You cannot buy stocks of a team going into BYE week!!!"]) return order = OrderService.create(user, stock, **order_dict) await self.reply([ f"Order **{order.id}** placed succesfully.", " ", f"**{order.desc()}**" ]) return
async def __run_stock(self): if (self.args[0]) == "!stock": detail = False if len(self.args) < 2: await self.reply([ "Incorrect number of arguments!!!", self.__class__.stock_help() ]) else: limit = 24 if self.args[1] in [ "top", "bottom", "hot", "net", "gain", "loss", "gain%", "loss%" ] and len(self.args) == 3 and represents_int( self.args[2]) and int(self.args[2]) > 0 and int( self.args[2]) <= limit: if self.args[1] == "top": stocks = Stock.find_top(self.args[2]) elif self.args[1] == "bottom": stocks = Stock.find_bottom(self.args[2]) elif self.args[1] == "net": stocks = Stock.find_net(self.args[2]) elif self.args[1] == "gain": stocks = Stock.find_gain(self.args[2]) elif self.args[1] == "gain%": stocks = Stock.find_gain_pct(self.args[2]) elif self.args[1] == "loss": stocks = Stock.find_loss(self.args[2]) elif self.args[1] == "loss%": stocks = Stock.find_loss_pct(self.args[2]) else: stocks = Stock.find_hot(self.args[2]) elif self.args[1] == "detail" and len(self.args) == 3: detail = True try: stock = Stock.find_by_code(self.args[2]) if not stock: await self.reply( [f"{self.args[2]} is not unique stock code"]) return stocks = [stock] except MultipleResultsFound as exc: await self.reply( [f"{self.args[2]} is not unique stock code"]) return else: stocks = Stock.find_all_by_name(" ".join(self.args[1:])) msg = [] change_desc = "Change" if self.args[1] not in [ "gain%", "loss%" ] else "Change%" msg.append( '{:5s} - {:25} {:<8s} {:>7s}{:>9s}{:>8s}{:>11s}'.format( "Code", "Team Name", "Division", "Price", change_desc, "Shares", "Net Worth")) msg.append(78 * "-") round_n = current_round() for stock in stocks[0:limit]: match = MatchService.get_game(stock.name, round_n=round_n) played = "Y" if match and match.match_uuid else "N" changed_value = stock.unit_price_change if self.args[ 1] not in ["gain%", "loss%"] else 0 if int( stock.unit_price ) == 0 else 100 * stock.unit_price_change / ( stock.unit_price - stock.unit_price_change) msg.append( '{:5s} - {:25} {:<8s} {:>7.2f}{:>8.2f}{:1s}{:>8d}{:>11.2f}' .format(stock.code, stock.name, stock.division, stock.unit_price, changed_value, played, stock.share_count, stock.net_worth)) if detail: round_n = app.config['ROUNDS_COLLECT'][-1] match = MatchService.get_game(stocks[0].name, round_n=round_n) if match: homeStock = Stock.find_all_by_name( match.homeTeamName.strip()) awayStock = Stock.find_all_by_name( match.awayTeamName.strip()) homePrice = 0 if not homeStock else homeStock[ 0].unit_price awayPrice = 0 if not awayStock else awayStock[ 0].unit_price homeChange = 0 if not homeStock else homeStock[ 0].unit_price_change awayChange = 0 if not awayStock else awayStock[ 0].unit_price_change homeRace = "N/A" if not homeStock else homeStock[0].race awayRace = "N/A" if not awayStock else awayStock[0].race msg.append(" ") msg.append(f"[Round {round_n} Match]") msg.append('{:>37s} | {:<36s}'.format( "Home", "Away")) msg.append(78 * "-") msg.append('{:>37s} | {:<36s}'.format( match.homeCoachName, match.awayCoachName)) msg.append('{:>37s} | {:<36s}'.format( match.homeTeamName, match.awayTeamName)) msg.append('{:>37s} | {:<36s}'.format( homeRace, awayRace)) msg.append('{:>37.2f} | {:<36.2f}'.format( homePrice, awayPrice)) msg.append('{:>37.2f} | {:<36.2f}'.format( homeChange, awayChange)) # only 1 stock msg.append(" ") msg.append("[Owners]") msg.append(" ") msg.append('{:32s}: {:>8s}{:>11s}'.format( "Name", "Shares", "Net Worth")) msg.append(78 * "-") for share in stocks[0].shares: msg.append('{:32s}: {:8d}{:11.2f}'.format( share.user.short_name(), share.units, round(share.units * share.stock.unit_price, 2))) msg.append(" ") msg.append("[History]") msg.append(" ") msg.append('{:20s}: {:<12s}{:<8s}{:<8s}{:<11s}'.format( "Date", "Unit Price", "Change", "Shares", "Net Worth")) msg.append(78 * "-") for sh in stocks[0].histories: msg.append( '{:20s}: {:10.2f}{:8.2f}{:8d}{:11.2f}'.format( str(sh.date_created), sh.unit_price, sh.unit_price_change, sh.units, round(sh.units * sh.unit_price, 2))) if len(stocks) > 20: msg.append("...") msg.append("More stock follows, narrow your search!") await self.reply(msg, block=True)
def list_messages(self, user): msg1 = [ f"**User:** {user.short_name()}\n", "```", "{:19s}: {:9.2f}".format("Bank", user.account().amount), "{:19s}: {:9.2f}".format("Shares Value", user.shares_value()), 30 * "-", "{:19s}: {:9.2f}".format("Balance", user.balance()), "{:19s}: {:9.2f}".format("This Week Gain", user.current_gain()), "{:19s}: {:9.2f}".format("Last Week Gain", user.week_gain(current_round() - 1)), "{:19s}: {:>9}".format( "Last Week Position", user.position(app.config['SEASON'], current_round() - 1)), "{:19s}: {:9d}".format("Points", user.points()), 30 * "-", ] for record in user.point_card().records: msg1.append("{:2d} points - {}".format(record.amount, record.reason)) msg1.extend([ "```", " ", f"**Shares:**", ]) msg2 = [] if user.shares: round_n = current_round() for share in user.shares: gain = round(share.stock.unit_price_change, 2) match = MatchService.get_game(share.stock.name, round_n=round_n) played = "Y" if match and match.match_uuid else "N" if gain > 0: gain = "+" + str(gain) elif gain == 0: gain = "0.00" else: gain = str(gain) msg2.append( '{:5s} - {:25s}: {:3d} x {:7.2f}, Change: {:>7s}, Played: {:1s}' .format(share.stock.code, share.stock.name, share.units, share.stock.unit_price, gain, played)) msg3 = [] msg3.append(" ") if user.orders: msg3.append(f"**Outstanding Orders:**") for order in user.orders: if not order.processed and order.operation == "sell": msg3.append(f"{order.id}. {order.desc()}") msg3.append(" ") for order in user.orders: if not order.processed and order.operation == "buy": msg3.append(f"{order.id}. {order.desc()}") msg3.append(" ") msg3.append(" ") msg3.append(f"**Balance history:**") msg4 = [] msg4.append('{:20s}: {:>8s}{:>13s}'.format("Date", "Shares", "Balance")) for history in sorted(user.balance_histories, key=lambda x: x.date_created, reverse=True)[:10]: msg4.append('{:20s}: {:>8d}{:>13.2f}'.format( str(history.date_created), history.shares, history.balance)) return msg1, msg2, msg3, msg4
async def __run_sell(self): user = User.get_by_discord_id(self.message.author.id) order_dict = { 'operation': "sell", 'season': app.config['SEASON'], 'week': current_round() } if user is None: await self.reply([ (f"User {self.message.author.mention} does not exist." "Use !newuser to create user first.") ]) return if len(self.args) not in [2, 3]: await self.reply([ "Incorrect number of arguments!!!", self.__class__.sell_help() ]) return if self.args[1] == "all": if len(user.shares): for share in user.shares: order = OrderService.create(user, share.stock, **order_dict) await self.reply([ f"Order placed succesfully.", " ", f"**{order.desc()}**" ]) else: await self.reply([f"You do not own any shares"]) else: try: stock = Stock.find_by_code(self.args[1]) except MultipleResultsFound as exc: await self.reply([ f"Stock code **{self.args[1]}** is not unique!!!", ]) return if not stock: await self.reply([f"Stock code **{self.args[1]}** not found!"]) return if len(self.args) == 3: if not represents_int(self.args[2]) or (represents_int( self.args[2]) and not int(self.args[2]) > 0): await self.reply( [f"**{self.args[2]}** must be whole positive number!"]) return else: order_dict['sell_shares'] = int(self.args[2]) share = Share.query.join(Share.user, Share.stock).filter( User.id == user.id, Stock.id == stock.id).one_or_none() if not share: await self.reply([ f"You do not own any shares of **{self.args[1]}** stock!" ]) return order = OrderService.create(user, stock, **order_dict) await self.reply([ f"Order **{order.id}** placed succesfully.", " ", f"**{order.desc()}**" ]) return
def current_gain(self): app = db.get_app() return self.balance() - self.account().snapshot_for_week(current_round()-1).amount
def __init__(self): app = db.get_app() self.season = app.config['SEASON'] self.amount = Decimal(self.INIT_CASH) self.make_snapshot(current_round()-1)
def main(argv): """main()""" try: opts, args = getopt.getopt(argv, "h") except getopt.GetoptError: print('process_orders.py -h') sys.exit(2) for opt, arg in opts: if opt == '-h': print("Process all queued orders") sys.exit(0) try: def chunk_orders(orders): group_count = 10 order_chunks = [ orders[i:i + group_count] for i in range(0, len(orders), group_count) ] for chunk in order_chunks: msg = [] for order in chunk: order = OrderService.process(order) msg.append(f"{order.user.mention()}: {order.result}") OrderNotificationService.notify("\n".join(msg)) AdminNotificationService.notify("Updating DB ...") StockService.update() AdminNotificationService.notify("Done") AdminNotificationService.notify("Closing market ...") OrderService.close() AdminNotificationService.notify("Done") AdminNotificationService.notify("Processing SELL orders...") orders = Order.query.order_by(asc(Order.date_created)).filter( Order.processed == False, Order.operation == "sell").all() chunk_orders(orders) AdminNotificationService.notify("Done") AdminNotificationService.notify("Processing BUY orders...") orders = Order.query.order_by(asc(Order.date_created)).filter( Order.processed == False, Order.operation == "buy").all() chunk_orders(orders) AdminNotificationService.notify("Done") AdminNotificationService.notify("Opening market...") OrderService.open() AdminNotificationService.notify("Done") # points and gains only after allowed if app.config['ALLOW_TRACKING']: AdminNotificationService.notify("Recording gains...") for user in User.query.all(): user.account().make_snapshot(current_round()) db.session.commit() AdminNotificationService.notify("Done") AdminNotificationService.notify("Recording positions...") sorted_users = UserService.week_gain(current_round(), User.query.count()) for i, (position, value, user) in enumerate(sorted_users): user.record_position(position) db.session.commit() AdminNotificationService.notify("Done") AdminNotificationService.notify("Awarding points...") for i, (position, value, user) in enumerate(sorted_users): if position > 25: break user.award_points( POINTS[position], f"Top {position} gain in week {current_round()}") OrderNotificationService.notify( f"{user.mention()}: Awarded {POINTS[position]} points for top {position} gain ({round(value,2)}) in week {current_round()}" ) db.session.commit() AdminNotificationService.notify("Done") else: AdminNotificationService.notify("Point awards skipped") except Exception as exc: AdminNotificationService.notify(str(exc)) raise exc