0
0
Lập trình
NM

Xây Dựng Trình Theo Dõi Danh Mục Crypto Với PyQt6

Đăng vào 5 ngày trước

• 5 phút đọc

Xây Dựng Trình Theo Dõi Danh Mục Crypto Với PyQt6

Trong bài viết này, chúng ta sẽ cùng khám phá cách xây dựng một ứng dụng desktop nhẹ nhàng để theo dõi danh mục đầu tư tiền điện tử bằng cách sử dụng thư viện PyQt6. Dự án này sẽ giúp bạn hiểu rõ hơn về cách làm việc với giao diện người dùng, xử lý sự kiện và đa luồng trong PyQt6.

Giới Thiệu Dự Án

Ứng dụng của chúng ta sẽ cung cấp ba chức năng chính:

  1. Tải Danh Mục - Nhập tệp CSV chứa thông tin danh mục đầu tư.
  2. Làm Mới Giá - Lấy giá hiện tại từ API của Kraken.
  3. Xuất CSV - Lưu dữ liệu đã cập nhật trở lại đĩa.

Trong quá trình phát triển, chúng ta sẽ áp dụng đa luồng để giao diện người dùng không bị treo, thêm hệ thống ghi log và tệp cấu hình để ánh xạ các ký hiệu danh mục sang các cặp giao dịch của Kraken.

Giao Diện Người Dùng Chính

Giao diện chính của ứng dụng bao gồm:

  • Một QTableWidget để hiển thị dữ liệu danh mục.
  • Các nút bấm để tải, làm mới và xuất dữ liệu.

Mã Nguồn Giao Diện Người Dùng

python Copy
# Đặt cấu hình giao diện

def setUI(self):
    self.setWindowTitle("CryptoTracker")
    self.portfolio = pd.DataFrame(columns=["symbol", "amount", "price", "total_value"])
    self.table = QTableWidget()
    self.btn_load = QPushButton("Tải Danh Mục CSV")
    self.btn_load.clicked.connect(self.load_portfolio)
    self.btn_refresh = QPushButton("Làm Mới Giá Kraken")
    self.btn_refresh.clicked.connect(self.refresh_prices)
    self.btn_export = QPushButton("Xuất ra CSV")
    self.btn_export.clicked.connect(self.export_csv)

    layout = QVBoxLayout()
    layout.addWidget(self.table)
    layout.addWidget(self.btn_load)
    layout.addWidget(self.btn_refresh)
    layout.addWidget(self.btn_export)

    container = QWidget()
    container.setLayout(layout)
    self.setCentralWidget(container)

Tải Danh Mục

Chúng ta sẽ sử dụng một tệp CSV đơn giản để điều khiển ứng dụng. Khi nhấn nút Tải Danh Mục, một hộp thoại sẽ mở ra cho phép người dùng chọn tệp CSV và hiển thị dữ liệu trong bảng.

Mã Nguồn Tải Danh Mục

python Copy
# Tải danh mục từ tệp CSV

def load_portfolio(self):
    file_name, _ = QFileDialog.getOpenFileName(self, "Mở CSV", "", "Tệp CSV (*.csv)")
    if file_name:
        self.portfolio = pd.read_csv(file_name)
        self.logger.info(f"Đã tải tệp {file_name}")
        self.update_table()

Ví Dụ Tệp portfolio.csv

csv Copy
symbol,amount
BTC,0.05
ETH,0.7
DOGE,1000

Lấy Giá (Với Đa Luồng)

Một trong những bài học quan trọng trong lập trình GUI là không bao giờ chặn luồng giao diện người dùng. Vì việc gọi API của Kraken có thể mất thời gian, chúng ta sẽ sử dụng QThreadPool với một lớp Worker tùy chỉnh:

Mã Nguồn Worker

python Copy
class Worker(QRunnable):
    def __init__(self, fn, *args, **kwargs):
        super().__init__()
        self.fn = fn
        self.args = args
        self.kwargs = kwargs

    @pyqtSlot()
    def run(self):
        self.fn(*self.args, **self.kwargs)

Khi người dùng nhấn nút Làm Mới Giá, mỗi ký hiệu sẽ được xử lý trong một luồng worker riêng biệt:

Mã Nguồn Làm Mới Giá

python Copy
# Làm mới giá từ Kraken

def refresh_prices(self):
    if self.portfolio.empty:
        self.logger.error("Không tìm thấy dữ liệu trong danh mục")
        return

    for sym in self.portfolio["symbol"]:
        kraken_pair = self.config['KrakenSymbols'][sym.upper()]
        worker = Worker(self.update_pair_info, kraken_pair, sym)
        self.threadPool.start(worker)

Ví Dụ Tệp config.ini với Ánh Xạ Ký Hiệu của Kraken

ini Copy
[KrakenSymbols]
BTC=XXBTZUSD
ETH=XETHZUSD
DOGE=XDGUSD
USDT=USDTZUSD
SOL=SOLUSD

Cập Nhật Bảng

Sau khi lấy giá, ứng dụng sẽ cập nhật cả DataFrame và bảng hiển thị:

Mã Nguồn Cập Nhật Bảng

python Copy
# Cập nhật bảng hiển thị

def update_table(self):
    self.table.setRowCount(len(self.portfolio))
    self.table.setColumnCount(len(self.portfolio.columns))
    self.table.setHorizontalHeaderLabels(self.portfolio.columns)

    for i, row in self.portfolio.iterrows():
        for j, col in enumerate(self.portfolio.columns):
            self.table.setItem(i, j, QTableWidgetItem(str(row[col])))

Mỗi hàng sẽ hiển thị:

  • Ký hiệu (ví dụ, BTC)
  • Số lượng (từ CSV)
  • Giá (từ Kraken)
  • Giá trị tổng (số lượng × giá)

Hệ Thống Ghi Log

Để theo dõi các hoạt động trong ứng dụng, chúng ta sẽ thêm một hệ thống ghi log đơn giản ghi vào cả app.log và console. Điều này rất hữu ích khi gỡ lỗi phản hồi API và đóng gói bằng PyInstaller.

Những Bài Học Rút Ra

  • Đa luồng là rất quan trọng: nếu không có nó, giao diện người dùng sẽ bị treo trong khi chờ phản hồi từ Kraken.
  • Cấu trúc của PyQt6 rất linh hoạt, nhưng việc lồng ghép các cấu trúc có thể cần một số thử nghiệm.
  • PyInstaller hoạt động, nhưng bạn cần xử lý các tài nguyên được đóng gói như config.ini một cách cẩn thận (mẹo sys._MEIPASS).
  • Kết hợp pandas với QTableWidget giúp dễ dàng đồng bộ hóa GUI và dữ liệu.

Demo và Mã Nguồn

Bạn có thể xem cách ứng dụng hoạt động tại đây. Mã nguồn có thể được tìm thấy tại đây.

Kết Luận

Hy vọng rằng bài viết này đã giúp bạn hiểu rõ hơn về cách xây dựng một ứng dụng theo dõi danh mục đầu tư tiền điện tử bằng PyQt6. Hãy thử triển khai và mở rộng ứng dụng của bạn để phù hợp với nhu cầu của mình. Nếu bạn có bất kỳ câu hỏi nào, đừng ngần ngại để lại câu hỏi bên dưới!

Câu Hỏi Thường Gặp (FAQ)

1. PyQt6 có khó học không?

PyQt6 có thể khó khăn cho người mới bắt đầu, nhưng với tài liệu và ví dụ rõ ràng, bạn có thể dễ dàng nắm bắt. Hãy thử làm theo các hướng dẫn và thực hành nhiều.

2. Tôi có thể sử dụng API khác không?

Có, bạn có thể thay thế API của Kraken bằng bất kỳ API nào khác phù hợp với nhu cầu của bạn. Hãy đảm bảo rằng bạn điều chỉnh mã theo API mà bạn đang sử dụng.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào