import random
import time
import json
import os
from datetime import datetime, timedelta
class Stock:
"""股票类"""
def __init__(self, code, name, initial_price):
self.code = code
self.name = name
self.price = initial_price
self.history = [initial_price]
self.volume = 0
self.last_price = initial_price # 添加上一日价格用于计算涨跌幅
def update_price(self):
"""更新股票价格(模拟市场波动)"""
# 保存上一日价格
self.last_price = self.price
# 随机价格波动,范围在-5%到+5%之间
change_rate = random.uniform(-0.05, 0.05)
self.price = round(self.price * (1 + change_rate), 2)
self.price = max(0.01, self.price) # 确保价格不会低于0.01
self.history.append(self.price)
# 保持历史记录在合理范围内
if len(self.history) > 100:
self.history = self.history[-100:]
# 模拟成交量
self.volume = random.randint(1000, 100000)
def get_change_rate(self):
"""获取涨跌幅"""
if self.last_price == 0:
return 0
return round((self.price - self.last_price) / self.last_price * 100, 2)
class Portfolio:
"""投资组合类"""
def __init__(self, username, initial_capital=100000):
self.username = username
self.cash = initial_capital
self.positions = {} # {股票代码: 股数}
self.total_invested = 0
self.initial_capital = initial_capital
self.transaction_history = [] # 添加交易历史
def buy_stock(self, stock_code, shares, stock_price):
"""买入股票"""
if shares <= 0:
return False, "股数必须大于0"
cost = shares * stock_price
if cost > self.cash:
return False, f"资金不足,需要 {cost:.2f} 元,当前现金 {self.cash:.2f} 元"
self.cash -= cost
if stock_code in self.positions:
self.positions[stock_code] += shares
else:
self.positions[stock_code] = shares
# 记录交易历史
self.transaction_history.append({
'type': 'buy',
'stock_code': stock_code,
'shares': shares,
'price': stock_price,
'total': cost,
'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
})
return True, f"成功买入 {shares} 股 {stock_code},花费 {cost:.2f} 元"
def sell_stock(self, stock_code, shares, stock_price):
"""卖出股票"""
if stock_code not in self.positions:
return False, "您没有持有该股票"
if self.positions[stock_code] < shares:
return False, f"持仓不足,当前持有 {self.positions[stock_code]} 股,要卖出 {shares} 股"
if shares <= 0:
return False, "股数必须大于0"
revenue = shares * stock_price
self.cash += revenue
self.positions[stock_code] -= shares
if self.positions[stock_code] == 0:
del self.positions[stock_code]
# 记录交易历史
self.transaction_history.append({
'type': 'sell',
'stock_code': stock_code,
'shares': shares,
'price': stock_price,
'total': revenue,
'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
})
return True, f"成功卖出 {shares} 股 {stock_code},获得 {revenue:.2f} 元"
def get_total_value(self, stock_market):
"""获取总资产价值"""
total = self.cash
for stock_code, shares in self.positions.items():
if stock_code in stock_market:
total += shares * stock_market[stock_code].price
return total
def get_profit_rate(self, stock_market):
"""获取收益率"""
total_value = self.get_total_value(stock_market)
if self.initial_capital == 0:
return 0
return round((total_value - self.initial_capital) / self.initial_capital * 100, 2)
def get_position_value(self, stock_code, stock_market):
"""获取某只股票的持仓价值"""
if stock_code not in self.positions:
return 0
if stock_code not in stock_market:
return 0
return self.positions[stock_code] * stock_market[stock_code].price
class StockMarket:
"""股票市场类"""
def __init__(self):
self.stocks = {}
self.initialize_market()
def initialize_market(self):
"""初始化股票市场"""
stock_list = [
("000001", "平安银行", 15.50),
("000002", "万科A", 25.80),
("000858", "五粮液", 180.00),
("002415", "海康威视", 45.60),
("600036", "招商银行", 38.90),
("600519", "贵州茅台", 1680.00),
("600887", "伊利股份", 32.50),
("000651", "格力电器", 58.70), # 修复重复代码
("002594", "比亚迪", 245.00),
("300059", "东方财富", 28.90)
]
for code, name, price in stock_list:
self.stocks[code] = Stock(code, name, price)
def update_all_prices(self):
"""更新所有股票价格"""
for stock in self.stocks.values():
stock.update_price()
def get_stock_info(self, code):
"""获取股票信息"""
if code in self.stocks:
stock = self.stocks[code]
return {
'code': stock.code,
'name': stock.name,
'price': stock.price,
'change_rate': stock.get_change_rate(),
'volume': stock.volume
}
return None
class GameManager:
"""游戏管理器"""
def __init__(self):
self.market = StockMarket()
self.players = {}
self.load_data()
def load_data(self):
"""加载游戏数据"""
try:
if os.path.exists('stock_game_data.json'):
with open('stock_game_data.json', 'r', encoding='utf-8') as f:
data = json.load(f)
for username, player_data in data.items():
self.players[username] = Portfolio(username, player_data.get('initial_capital', 100000))
self.players[username].cash = player_data.get('cash', 100000)
self.players[username].positions = player_data.get('positions', {})
self.players[username].transaction_history = player_data.get('transaction_history', [])
except Exception as e:
print(f"加载数据时出错: {e}")
def save_data(self):
"""保存游戏数据"""
data = {}
for username, player in self.players.items():
data[username] = {
'initial_capital': player.initial_capital,
'cash': player.cash,
'positions': player.positions,
'transaction_history': player.transaction_history
}
try:
with open('stock_game_data.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
except Exception as e:
print(f"保存数据时出错: {e}")
def register_player(self, username):
"""注册新玩家"""
if not username or username.strip() == "":
return False, "用户名不能为空"
username = username.strip()
if username in self.players:
return False, "用户名已存在"
self.players[username] = Portfolio(username)
self.save_data()
return True, f"欢迎 {username} 加入模拟炒股游戏!初始资金:100,000元"
def get_leaderboard(self):
"""获取排行榜"""
leaderboard = []
for username, player in self.players.items():
total_value = player.get_total_value(self.market)
profit_rate = player.get_profit_rate(self.market)
leaderboard.append({
'username': username,
'total_value': total_value,
'profit_rate': profit_rate
})
leaderboard.sort(key=lambda x: x['total_value'], reverse=True)
return leaderboard
def display_menu():
"""显示主菜单"""
print("\n" + "="*50)
print(" 🚀 模拟炒股游戏 ��")
print("="*50)
print("1. 注册/登录")
print("2. 查看股票行情")
print("3. 买入股票")
print("4. 卖出股票")
print("5. 查看我的账户")
print("6. 查看排行榜")
print("7. 查看交易历史")
print("8. 退出游戏")
print("="*50)
def display_stock_market(market):
"""显示股票行情"""
print("\n📈 股票行情")
print("-" * 80)
print(f"{'代码':<8} {'名称':<12} {'当前价格':<10} {'涨跌幅':<8} {'成交量':<10}")
print("-" * 80)
for stock in market.stocks.values():
change_rate = stock.get_change_rate()
change_symbol = "��" if change_rate > 0 else "��" if change_rate < 0 else "➡️"
print(f"{stock.code:<8} {stock.name:<12} {stock.price:<10.2f} {change_symbol}{change_rate:>6.2f}% {stock.volume:<10,}")
def display_portfolio(player, market):
"""显示投资组合"""
print(f"\n�� {player.username} 的投资组合")
print("-" * 60)
print(f"现金余额: {player.cash:,.2f} 元")
print(f"总资产: {player.get_total_value(market):,.2f} 元")
print(f"收益率: {player.get_profit_rate(market):.2f}%")
print("-" * 60)
if player.positions:
print("持仓明细:")
print(f"{'股票代码':<8} {'股票名称':<12} {'持仓数量':<8} {'当前价值':<12} {'盈亏':<8}")
print("-" * 60)
for stock_code, shares in player.positions.items():
if stock_code in market.stocks:
stock = market.stocks[stock_code]
current_value = shares * stock.price
# 这里可以添加成本价计算,暂时简化
print(f"{stock_code:<8} {stock.name:<12} {shares:<8} {current_value:<12.2f} {'--':<8}")
else:
print("暂无持仓")
def display_transaction_history(player):
"""显示交易历史"""
if not player.transaction_history:
print("暂无交易记录")
return
print(f"\n�� {player.username} 的交易历史")
print("-" * 80)
print(f"{'时间':<19} {'类型':<6} {'股票代码':<8} {'股数':<6} {'价格':<8} {'总额':<12}")
print("-" * 80)
for transaction in player.transaction_history[-20:]: # 只显示最近20条
trans_type = "买入" if transaction['type'] == 'buy' else "卖出"
print(f"{transaction['timestamp']:<19} {trans_type:<6} {transaction['stock_code']:<8} "
f"{transaction['shares']:<6} {transaction['price']:<8.2f} {transaction['total']:<12.2f}")
def validate_input(prompt, input_type="str", min_value=None, max_value=None):
"""验证用户输入"""
while True:
try:
user_input = input(prompt).strip()
if input_type == "int":
value = int(user_input)
if min_value is not None and value < min_value:
print(f"❌ 输入值不能小于 {min_value}")
continue
if max_value is not None and value > max_value:
print(f"❌ 输入值不能大于 {max_value}")
continue
return value
elif input_type == "float":
value = float(user_input)
if min_value is not None and value < min_value:
print(f"❌ 输入值不能小于 {min_value}")
continue
if max_value is not None and value > max_value:
print(f"❌ 输入值不能大于 {max_value}")
continue
return value
else:
if not user_input:
print("❌ 输入不能为空")
continue
return user_input
except ValueError:
print("❌ 输入格式错误,请重新输入")
def main():
"""主游戏循环"""
game = GameManager()
current_player = None
print("🎮 欢迎来到模拟炒股游戏!")
print("💡 提示:游戏会自动保存您的交易记录")
while True:
try:
display_menu()
choice = input("\n请选择操作 (1-8): ").strip()
if choice == '1':
# 注册/登录
username = validate_input("请输入用户名: ")
if username in game.players:
current_player = game.players[username]
print(f"✅ 欢迎回来,{username}!")
else:
success, message = game.register_player(username)
print(message)
if success:
current_player = game.players[username]
elif choice == '2':
# 查看股票行情
game.market.update_all_prices()
display_stock_market(game.market)
elif choice == '3':
# 买入股票
if not current_player:
print("❌ 请先登录")
continue
display_stock_market(game.market)
stock_code = validate_input("请输入要买入的股票代码: ")
if stock_code not in game.market.stocks:
print("❌ 股票代码不存在")
continue
shares = validate_input("请输入要买入的股数: ", "int", 1)
stock = game.market.stocks[stock_code]
success, message = current_player.buy_stock(stock_code, shares, stock.price)
print(message)
if success:
game.save_data()
elif choice == '4':
# 卖出股票
if not current_player:
print("❌ 请先登录")
continue
if not current_player.positions:
print("❌ 您没有持仓")
continue
display_portfolio(current_player, game.market)
stock_code = validate_input("请输入要卖出的股票代码: ")
if stock_code not in current_player.positions:
print("❌ 您没有持有该股票")
continue
max_shares = current_player.positions[stock_code]
shares = validate_input(f"请输入要卖出的股数 (最多 {max_shares} 股): ", "int", 1, max_shares)
stock = game.market.stocks[stock_code]
success, message = current_player.sell_stock(stock_code, shares, stock.price)
print(message)
if success:
game.save_data()
elif choice == '5':
# 查看我的账户
if not current_player:
print("❌ 请先登录")
continue
display_portfolio(current_player, game.market)
elif choice == '6':
# 查看排行榜
if not game.players:
print("❌ 暂无玩家数据")
continue
leaderboard = game.get_leaderboard()
print("\n🏆 排行榜")
print("-" * 60)
print(f"{'排名':<4} {'用户名':<12} {'总资产':<15} {'收益率':<8}")
print("-" * 60)
for i, player_data in enumerate(leaderboard, 1):
rank_emoji = "🥇" if i == 1 else "🥈" if i == 2 else "🥉" if i == 3 else f"{i:2d}"
print(f"{rank_emoji:<4} {player_data['username']:<12} {player_data['total_value']:<15,.2f} {player_data['profit_rate']:>6.2f}%")
elif choice == '7':
# 查看交易历史
if not current_player:
print("❌ 请先登录")
continue
display_transaction_history(current_player)
elif choice == '8':
# 退出游戏
print("👋 感谢游玩模拟炒股游戏!再见!")
game.save_data()
break
else:
print("❌ 无效选择,请重新输入")
input("\n按回车键继续...")
except KeyboardInterrupt:
print("\n\n⚠️ 检测到中断信号,正在保存数据...")
game.save_data()
print("👋 游戏已保存,再见!")
break
except Exception as e:
print(f"❌ 发生错误: {e}")
print("请重新开始游戏")
input("按回车键继续...")
if __name__ == "__main__":
main()


2953

被折叠的 条评论
为什么被折叠?



