個人股票投資管理工具的開發指南
使用 PyQt6 和 SQLite 打造現代化的投資管理應用
關鍵要點
- 全面的交易記錄管理:詳細記錄每筆交易,並自動計算盈虧情況。
- 多投資組合分析功能:支持多個投資組合,提供深入的損益分析。
- 即時數據更新與報告生成:整合實時數據,生成多樣化的投資報告。
1. 交易記錄與管理
1.1 功能描述
交易記錄與管理是個人股票投資管理工具的核心功能。該功能允許用戶記錄每筆股票交易的詳細信息,包括股票代碼、購買價格、購買日期、數量等,並自動計算每筆交易的盈利或虧損百分比,幫助用戶實時了解投資表現。
1.2 實現方法
1.2.1 資料庫設計
使用 SQLite 數據庫來存儲交易記錄,設計一個名為 transactions 的表,包含以下字段:
CREATE TABLE transactions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
stock_symbol TEXT NOT NULL,
purchase_price REAL NOT NULL,
purchase_date TEXT NOT NULL,
quantity INTEGER NOT NULL,
current_price REAL,
profit_loss REAL
);
1.2.2 使用 PyQt6 顯示與管理交易記錄
利用 PyQt6 的 QTableWidget 或 QTableView 來顯示交易記錄,並提供一個表單讓用戶輸入交易信息。以下是一個簡單的交易記錄管理功能的代碼示例:
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QTableWidget, QTableWidgetItem, QVBoxLayout, QWidget, QPushButton, QLineEdit, QDateEdit, QLabel
from PyQt6.QtSql import QSqlDatabase, QSqlQuery
class StockManagementApp(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("個人股票投資管理工具")
self.setGeometry(100, 100, 800, 600)
# 數據庫連接
self.db = QSqlDatabase.addDatabase("QSQLITE")
self.db.setDatabaseName("stock_management.db")
if not self.db.open():
print("無法連接數據庫")
# 創建表
query = QSqlQuery()
query.exec("""
CREATE TABLE IF NOT EXISTS transactions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
stock_symbol TEXT NOT NULL,
purchase_price REAL NOT NULL,
purchase_date TEXT NOT NULL,
quantity INTEGER NOT NULL
)
""")
# 界面組件
self.table = QTableWidget(self)
self.table.setColumnCount(4)
self.table.setHorizontalHeaderLabels(["股票代碼", "購買價格", "購買日期", "數量"])
self.symbol_input = QLineEdit(self)
self.price_input = QLineEdit(self)
self.date_input = QDateEdit(self)
self.quantity_input = QLineEdit(self)
self.add_button = QPushButton("添加交易", self)
self.add_button.clicked.connect(self.add_transaction)
# 布局
layout = QVBoxLayout()
layout.addWidget(self.table)
layout.addWidget(QLabel("股票代碼"))
layout.addWidget(self.symbol_input)
layout.addWidget(QLabel("購買價格"))
layout.addWidget(self.price_input)
layout.addWidget(QLabel("購買日期"))
layout.addWidget(self.date_input)
layout.addWidget(QLabel("數量"))
layout.addWidget(self.quantity_input)
layout.addWidget(self.add_button)
container = QWidget()
container.setLayout(layout)
self.setCentralWidget(container)
# 加載數據
self.load_data()
def load_data(self):
query = QSqlQuery("SELECT stock_symbol, purchase_price, purchase_date, quantity FROM transactions")
self.table.setRowCount(0)
while query.next():
row = self.table.rowCount()
self.table.insertRow(row)
for col in range(4):
self.table.setItem(row, col, QTableWidgetItem(str(query.value(col))))
def add_transaction(self):
symbol = self.symbol_input.text()
price = float(self.price_input.text())
date = self.date_input.date().toString("yyyy-MM-dd")
quantity = int(self.quantity_input.text())
query = QSqlQuery()
query.prepare("""
INSERT INTO transactions (stock_symbol, purchase_price, purchase_date, quantity)
VALUES (?, ?, ?, ?)
""")
query.addBindValue(symbol)
query.addBindValue(price)
query.addBindValue(date)
query.addBindValue(quantity)
query.exec()
self.load_data()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = StockManagementApp()
window.show()
sys.exit(app.exec())
1.2.3 盈利與虧損計算
定期更新當前價格,並計算每筆交易的盈利或虧損百分比。示例代碼如下:
profit_loss = (current_price - purchase_price) * quantity
profit_loss_percentage = (profit_loss / (purchase_price * quantity)) * 100
1.2.4 界面美化
使用 Qt Style Sheets (QSS) 美化界面,例如設置背景顏色、按鈕樣式等:
QWidget {
background-color: #f0f0f0;
font-family: "Segoe UI";
}
QPushButton {
background-color: #4CAF50;
color: white;
border-radius: 5px;
padding: 10px;
}
2. 多種投資組合分析
2.1 功能描述
多種投資組合分析功能允許用戶同時管理和分析多個投資組合,並提供詳細的損益視圖,包括未實現收益和已實現收益。這有助於用戶全面了解其投資表現,並做出更明智的投資決策。
2.2 實現方法
2.2.1 投資組合資料庫設計
在資料庫中創建一個 portfolios 表來存儲不同的投資組合信息:
CREATE TABLE portfolios (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
description TEXT
);
2.2.2 多投資組合管理介面
使用 QComboBox 讓用戶選擇不同的投資組合,並顯示相關的損益視圖。示例代碼如下:
self.portfolio_combobox = QComboBox(self)
self.portfolio_combobox.currentIndexChanged.connect(self.update_portfolio_view)
def update_portfolio_view(self, index):
portfolio_id = self.get_selected_portfolio_id(index)
# 根據 portfolio_id 加載相關數據並更新視圖
2.2.3 損益計算與視覺化
計算每個投資組合的未實現收益和已實現收益,並使用 QChart 或 Matplotlib 繪製收益趨勢圖:
import matplotlib.pyplot as plt
def plot_profit_loss(self, data):
dates = [item['date'] for item in data]
profit = [item['profit'] for item in data]
plt.plot(dates, profit, marker='o')
plt.title('收益趨勢圖')
plt.xlabel('日期')
plt.ylabel('收益')
plt.show()
2.2.4 表格與圖表的整合
使用 QTableView 展示詳細的交易數據,同時在旁邊顯示圖表,以便用戶直觀地看到投資表現。
3. 即時數據與報告
3.1 功能描述
即時數據與報告功能提供最新的投資數據,並生成多樣化的報告。這包括與金融賬戶同步、實時更新股票價格、以及生成月報或年報,讓用戶隨時掌握其資產狀況。
3.2 實現方法
3.2.1 整合實時數據 API
使用第三方 API(如 Yahoo Finance 或 Alpha Vantage)獲取即時股票數據。示例代碼如下:
import yfinance as yf
def get_latest_price(symbol):
ticker = yf.Ticker(symbol)
data = ticker.history(period="1d")
latest_price = data['Close'][-1]
return latest_price
3.2.2 定期更新數據庫
設置定時任務,定期更新數據庫中的 current_price 字段,並重新計算盈虧百分比:
import schedule
import time
def update_prices():
query = QSqlQuery("SELECT id, stock_symbol, purchase_price, quantity FROM transactions")
while query.next():
id = query.value(0)
symbol = query.value(1)
purchase_price = query.value(2)
quantity = query.value(3)
current_price = get_latest_price(symbol)
profit_loss = (current_price - purchase_price) * quantity
profit_loss_percentage = (profit_loss / (purchase_price * quantity)) * 100
update_query = QSqlQuery()
update_query.prepare("""
UPDATE transactions
SET current_price = ?, profit_loss = ?
WHERE id = ?
""")
update_query.addBindValue(current_price)
update_query.addBindValue(profit_loss_percentage)
update_query.addBindValue(id)
update_query.exec()
schedule.every().day.at("18:00").do(update_prices)
while True:
schedule.run_pending()
time.sleep(1)
3.2.3 報告生成
使用 pandas 和 reportlab 庫來生成 CSV 或 PDF 格式的報告:
import pandas as pd
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
def generate_report():
query = QSqlQuery("SELECT * FROM transactions")
data = []
while query.next():
data.append({
'symbol': query.value('stock_symbol'),
'purchase_price': query.value('purchase_price'),
'current_price': query.value('current_price'),
'quantity': query.value('quantity'),
'profit_loss': query.value('profit_loss')
})
df = pd.DataFrame(data)
df.to_csv('report.csv', index=False)
# 生成 PDF 報告
c = canvas.Canvas("report.pdf", pagesize=letter)
c.drawString(100, 750, "個人股票投資報告")
# 添加更多內容
c.save()
4. 多樣化的投資選擇
4.1 功能描述
多樣化的投資選擇允許用戶追蹤多種資產類型,包括股票、債券、加密貨幣等,並提供市場監控和投資組合優化功能,幫助用戶制定更有效的投資策略。
4.2 實現方法
4.2.1 擴展資料庫結構
在 transactions 表中增加 asset_type 字段來區分不同的資產類型:
ALTER TABLE transactions ADD COLUMN asset_type TEXT;
4.2.2 多資產類型管理介面
使用 QTabWidget 創建多個頁面,分別顯示不同資產的投資情況。例如,股票、債券、加密貨幣等各有一個頁籤:
self.tab_widget = QTabWidget()
self.tab_widget.addTab(StocksTab(), "股票")
self.tab_widget.addTab(BondsTab(), "債券")
self.tab_widget.addTab(CryptoTab(), "加密貨幣")
layout.addWidget(self.tab_widget)
4.2.3 市場監控功能
顯示各類資產的實時價格和趨勢圖,幫助用戶追蹤市場動態。以下是一個簡單的實現範例:
def display_market_trends(asset_type):
symbols = get_symbols_by_asset_type(asset_type)
prices = [get_latest_price(symbol) for symbol in symbols]
plt.bar(symbols, prices)
plt.title(f"{asset_type} 市場價格")
plt.xlabel("符號")
plt.ylabel("價格")
plt.show()
5. 現代化使用者介面設計
5.1 設計建議
為了提供現代化且優美的使用者介面,應該採用以下設計建議:
-
使用 QSS 美化界面,設置一致的色彩方案和字體風格。
-
利用
QMainWindow創建主窗口,包含菜單欄、工具欄和狀態欄,提供易用的導航和操作介面。 -
使用
QStackedWidget實現多頁面切換功能,保持介面的整潔和一致。
5.2 界面佈局與導航
設計一個直觀的界面佈局,使用頂部工具欄和側邊導航欄來切換不同的功能模塊。以下是一個簡單的主窗口佈局代碼示例:
from PyQt6.QtWidgets import QMainWindow, QToolBar, QAction, QTabWidget, QWidget, QVBoxLayout
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("個人股票投資管理系統")
self.resize(1200, 800)
# 建立頂部工具列
toolbar = QToolBar()
self.addToolBar(toolbar)
# 新增功能按鈕
add_transaction_btn = QAction("新增交易", self)
portfolio_analysis_btn = QAction("投資組合分析", self)
reports_btn = QAction("報表匯出", self)
toolbar.addAction(add_transaction_btn)
toolbar.addAction(portfolio_analysis_btn)
toolbar.addAction(reports_btn)
# 建立分頁介面
self.tab_widget = QTabWidget()
self.setCentralWidget(self.tab_widget)
# 新增各功能分頁
self.positions_tab = PositionsTab()
self.transactions_tab = TransactionsTab()
self.analysis_tab = AnalysisTab()
self.tab_widget.addTab(self.positions_tab, "持股部位")
self.tab_widget.addTab(self.transactions_tab, "交易記錄")
self.tab_widget.addTab(self.analysis_tab, "績效分析")
5.3 視覺效果與用戶體驗
使用現代化的色彩搭配和排版,提升用戶體驗。例如,採用深色主題來減少長時間使用的眼睛疲勞:
QWidget {
background-color: #2e2e2e;
color: #ffffff;
font-family: "Arial";
}
QPushButton {
background-color: #388278;
color: white;
border-radius: 5px;
padding: 10px;
}
6. 數據庫連接與管理
6.1 實現方法
6.1.1 連接 SQLite 數據庫
使用 PyQt6 的 QSqlDatabase 連接 SQLite 數據庫,並處理連接失敗的情況:
from PyQt6.QtSql import QSqlDatabase, QSqlQuery
def connect_database():
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("stock_portfolio.db")
if not db.open():
print("無法連接數據庫")
return False
return True
6.1.2 數據庫模型與界面組件綁定
使用 QSqlTableModel 或 QSqlQueryModel 將數據庫中的數據與界面組件(如表格視圖)進行綁定,實現數據的動態顯示與更新:
from PyQt6.QtSql import QSqlTableModel
class TransactionsTab(QWidget):
def __init__(self):
super().__init__()
layout = QVBoxLayout(self)
self.table_view = QTableView()
self.model = QSqlTableModel()
self.model.setTable("transactions")
self.model.select()
self.model.setHeaderData(1, Qt.Horizontal, "股票代號")
self.model.setHeaderData(2, Qt.Horizontal, "交易類型")
self.model.setHeaderData(3, Qt.Horizontal, "價格")
self.model.setHeaderData(4, Qt.Horizontal, "數量")
self.model.setHeaderData(5, Qt.Horizontal, "交易日期")
self.table_view.setModel(self.model)
layout.addWidget(self.table_view)
7. 完整代碼示例
7.1 主應用程式結構
以下是一個綜合性較強的應用程式結構示例,包括數據庫連接、界面設計和主要功能模塊:
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QLabel, QTableWidget, QTableWidgetItem, QPushButton, QComboBox, QTabWidget, QWidget
from PyQt6.QtSql import QSqlDatabase, QSqlQuery
import yfinance as yf
import matplotlib.pyplot as plt
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("個人股票投資管理工具")
self.setGeometry(100, 100, 1200, 800)
# 數據庫連接
self.db = QSqlDatabase.addDatabase("QSQLITE")
self.db.setDatabaseName("stock_portfolio.db")
if not self.db.open():
print("無法連接數據庫")
sys.exit(1)
# 創建表
self.create_tables()
# 建立主要佈局
main_widget = QWidget()
self.setCentralWidget(main_widget)
layout = QVBoxLayout(main_widget)
# 建立頂部工具列
toolbar = QToolBar()
self.addToolBar(toolbar)
add_transaction_btn = QAction("新增交易", self)
portfolio_analysis_btn = QAction("投資組合分析", self)
reports_btn = QAction("報表匯出", self)
toolbar.addAction(add_transaction_btn)
toolbar.addAction(portfolio_analysis_btn)
toolbar.addAction(reports_btn)
# 建立分頁介面
self.tab_widget = QTabWidget()
layout.addWidget(self.tab_widget)
# 新增各功能分頁
self.positions_tab = PositionsTab()
self.transactions_tab = TransactionsTab()
self.analysis_tab = AnalysisTab()
self.tab_widget.addTab(self.positions_tab, "持股部位")
self.tab_widget.addTab(self.transactions_tab, "交易記錄")
self.tab_widget.addTab(self.analysis_tab, "績效分析")
def create_tables(self):
query = QSqlQuery()
query.exec("""
CREATE TABLE IF NOT EXISTS stocks (
symbol TEXT PRIMARY KEY,
name TEXT,
market TEXT,
category TEXT
)
""")
query.exec("""
CREATE TABLE IF NOT EXISTS transactions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
stock_symbol TEXT,
trade_type TEXT,
price REAL,
shares INTEGER,
trade_date DATE,
commission REAL,
notes TEXT,
asset_type TEXT,
FOREIGN KEY (stock_symbol) REFERENCES stocks(symbol)
)
""")
query.exec("""
CREATE TABLE IF NOT EXISTS portfolios (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
description TEXT
)
""")
class TransactionsTab(QWidget):
def __init__(self):
super().__init__()
layout = QVBoxLayout(self)
# 交易記錄表格
self.table = QTableView()
self.model = QSqlTableModel()
self.model.setTable("transactions")
self.model.select()
# 設定表格欄位
self.model.setHeaderData(1, Qt.Horizontal, "股票代號")
self.model.setHeaderData(2, Qt.Horizontal, "交易類型")
self.model.setHeaderData(3, Qt.Horizontal, "價格")
self.model.setHeaderData(4, Qt.Horizontal, "數量")
self.model.setHeaderData(5, Qt.Horizontal, "交易日期")
self.table.setModel(self.model)
layout.addWidget(self.table)
class AnalysisTab(QWidget):
def __init__(self):
super().__init__()
layout = QVBoxLayout(self)
# 圖表區域
self.chart_view = QLabel("此處顯示績效圖表")
layout.addWidget(self.chart_view)
# 統計數據區域
stats_group = QGroupBox("投資統計")
stats_layout = QGridLayout()
self.total_value_label = QLabel("總市值: ")
self.profit_loss_label = QLabel("未實現損益: ")
self.return_rate_label = QLabel("報酬率: ")
stats_layout.addWidget(self.total_value_label, 0, 0)
stats_layout.addWidget(self.profit_loss_label, 0, 1)
stats_layout.addWidget(self.return_rate_label, 0, 2)
stats_group.setLayout(stats_layout)
layout.addWidget(stats_group)
class PositionsTab(QWidget):
def __init__(self):
super().__init__()
layout = QVBoxLayout(self)
self.label = QLabel("持股部位詳情")
layout.addWidget(self.label)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
8. 結論
利用 PyQt6 和 SQLite 可以輕鬆開發一款功能全面且現代化的個人股票投資管理工具。通過詳細的交易記錄管理、多投資組合分析、即時數據更新與報告生成以及多樣化的投資選擇,能夠滿足用戶對於投資管理的多方面需求。此外,通過應用現代化的使用者介面設計,提供良好的用戶體驗,讓投資管理變得更加高效和愉悅。未來可以進一步擴展功能,如加入警示系統、更多圖表分析等,提升應用的實用性和競爭力。
參考資料
Last updated January 22, 2025