↓Chuyển đến nội dung chính
  1. Bài viết/

MdevTrade: từ ý tưởng đến lúc hoàn thiện một AI Trading Agent

Nhật ký tôi dựng một hệ thống AI tự phân tích và mua bán vàng token hóa, phỏng theo một dự án mã nguồn mở. Bài kể việc nào giao cho AI, việc nào bắt buộc để code thường làm, và vì sao ranh giới đó quyết định tài khoản còn hay mất.

I. Một dự án trên GitHub và một câu hỏi #

Nhật ký tôi dựng một hệ thống AI tự phân tích và mua bán vàng token hóa, phỏng theo một dự án mã nguồn mở. Bài kể việc nào giao cho AI, việc nào bắt buộc để code thường làm, và vì sao ranh giới đó quyết định tài khoản còn hay mất.

Một nhóm AI tự đọc tin, cãi nhau, rồi quyết định mua hay bán. Tôi gặp ý tưởng đó vào một buổi tối rảnh rỗi, khi đang lướt GitHub, nơi lập trình viên chia sẻ mã nguồn. Dự án tên là TradingAgents, tại https://github.com/TauricResearch/TradingAgents, và tôi fork nó theo phản xạ. Fork là sao nguyên một dự án về tài khoản của mình để sửa tùy ý.

Phần mềm giao dịch tự động thông thường chạy bằng luật viết sẵn, kiểu “giá vượt mốc này thì mua”. TradingAgents làm khác: nó dựng một phòng giao dịch thu nhỏ ngay trong máy tính, mỗi vai do một AI đảm nhận. Có người đọc tin, một phe bênh giá lên và một phe bênh giá xuống cãi nhau, và một người quản lý chốt quyết định.

Các vai này đều do LLM đóng. LLM là mô hình ngôn ngữ lớn, loại AI đứng sau ChatGPT: nhận vào chữ, viết ra chữ. Một LLM được giao một vai, một nhiệm vụ và vài công cụ riêng thì gọi là một agent.

Câu hỏi của tôi lúc đó: LLM có thật sự tổng hợp được tin kinh tế để đoán thị trường không? Hay những đoạn suy luận nghe rất sắc kia chỉ là chữ được ghép theo xác suất cho có vẻ hợp lý?

Để tự tìm câu trả lời, tôi giữ ý tưởng cốt lõi của dự án và viết lại thành một bản thí nghiệm, an toàn hơn. Hệ thống có làm tốt không thì thú thật tôi chưa biết, nhưng tôi đã bấm nút chạy rồi. Cứ để nó chạy một thời gian, xem nó đốt hết tiền hay giúp tôi có lãi.

Để đêm còn kê cao gối ngủ, tôi đặt bốn giới hạn rủi ro cứng:

  • Không margin, không đòn bẩy. Margin là vay tiền của sàn giao dịch để mua nhiều hơn số vốn mình có; đòn bẩy là số lần được nhân lên, ví dụ gấp 5 lần vốn. Lãi và lỗ đều nhân theo.

    Lỗ gần hết phần tiền của mình là sàn tự bán để thu nợ, dân trong nghề gọi là cháy tài khoản.

  • Chỉ mua bán spot. Spot là mua đứt: trả tiền, nhận tài sản về ví, như mua vàng ở tiệm rồi cầm về nhà. Spot chỉ tốn phí mỗi lần mua bán, nên giữ lâu cũng không tốn thêm. Giao dịch vay và hợp đồng phái sinh, loại hợp đồng ăn theo giá mà không cần sở hữu tài sản, có thể tính phí suốt thời gian giữ lệnh.

  • Mua đều theo kiểu DCA. DCA, viết tắt của dollar-cost averaging, là chia tiền ra mua nhiều lần đều đặn thay vì dồn một lần. Giống người mỗi tháng lãnh lương là ghé tiệm vàng mua một ít, không ngồi đoán ngày nào vàng rẻ nhất.

    Lần mua trúng giá cao, lần trúng giá thấp, nên giá vốn trung bình nằm đâu đó ở giữa. Giá vốn trung bình là tổng tiền đã bỏ ra chia cho tổng lượng đã mua. Nó không đẹp bằng mua đúng đáy, nhưng không cần đoán đáy và tránh được cảnh dồn hết tiền đúng đỉnh.

  • Chỉ một tài sản: vàng token hóa, cặp XAUT/USDT. Token là đơn vị tài sản số mua bán trên sàn tiền mã hóa; mỗi XAUT được bảo chứng bằng vàng vật chất. USDT là đồng tiền số được thiết kế để giữ giá ngang một đô la Mỹ, nên cặp này nghĩa là giá XAUT tính bằng đô.

Toàn bộ bản tùy biến này tôi chia sẻ công khai. Phần dưới là những gì tôi đọc được trước khi code, và cách tôi dựng hệ thống từ đó.

II. Năm điều tôi đọc được trước khi viết code #

Trước khi đụng vào code, tôi đọc các tài liệu nghiên cứu để xem ý tưởng này có đứng vững không. Năm kết luận dưới đây quyết định gần như mọi chỗ tôi sửa so với dự án gốc.

1. Tin tức chỉ đẩy giá trong vài ngày đến vài tuần #

Ý tưởng ban đầu của tôi khá tham lam: dùng AI dự báo xu hướng xa 2 đến 6 tháng.

Nhưng các nghiên cứu cho thấy tin tài chính có thời gian bán hủy rất ngắn. Thời gian bán hủy là chữ mượn từ vật lý hạt nhân: sau khoảng thời gian đó, một nửa tác động của tin đã tan khỏi giá. Với tin tài chính, khoảng đó tính bằng ngày và tuần, không phải tháng.

Tin ra, người mua bán phản ứng, giá dịch chuyển; ai cũng phản ứng xong thì tin hết sức đẩy giá. Giống một tin nóng trên mạng xã hội: hôm đầu ai cũng bàn, tuần sau không ai nhắc.

Bắt mô hình dự báo quá xa thì nó không thấy được những cú sốc chưa xảy ra. LLM cũng hiếm khi trả lời “tôi không biết”; nó hay kéo dài xu hướng hôm nay sang tháng sau như kẻ một đường thẳng. Đặt tiền theo đường thẳng đó là công thức của thảm họa.

  • Tùy biến của tôi: rút khung dự báo về 1 đến 4 tuần, khoảng thời gian LLM tổng hợp tâm lý thị trường tốt nhất.

    Tầng thực thi, tức phần code trực tiếp đặt lệnh (xem Mục III), chốt lời theo ATR. Chốt lời là tự bán khi giá lên tới một mức đặt trước để giữ phần lãi.

    ATR, viết tắt của average true range, đo mức giá nhảy lên xuống trong một ngày bình thường, lấy trung bình qua những ngày gần nhất. Lấy ATR làm mốc thì điểm chốt lời tự nới ra khi thị trường chạy mạnh và thu lại khi thị trường yên, thay vì cố định một con số.

2. Đừng bắt LLM làm toán #

Một cái bẫy phổ biến là ném nguyên 200 ngày dữ liệu giá vào prompt, rồi mong mô hình tự “nhìn” ra đường trung bình 200 ngày. Prompt là toàn bộ chỉ dẫn và dữ liệu gửi cho LLM trong một lần hỏi.

LLM giỏi xử lý chữ, nhưng tính toán trên một dãy số dài thì không đáng tin: nó không thật sự cộng trừ, mà đoán con số nào trông hợp lý. Nhồi cả đống số vào còn làm nó dễ bỏ sót đúng phần quan trọng. Kết quả có thể là một bài phân tích rất mạch lạc, dựa trên một con số trung bình tính sai.

  • Tùy biến của tôi: tách hẳn việc tính khỏi việc suy luận.

    Trong MdevTrade, agent phân tích thị trường không tự tính. Nó gọi hai thư viện Python, tức bộ code viết sẵn để dùng lại: yfinance để lấy dữ liệu giá, stockstats để tính các chỉ báo kỹ thuật. Chỉ báo kỹ thuật là những con số tính từ lịch sử giá để đọc xu hướng.

    SMA là giá trung bình của N ngày gần nhất; SMA 200 là trung bình 200 ngày, dùng để xem xu hướng dài. MACD so một đường giá trung bình ngắn với một đường dài để bắt lúc xu hướng đổi chiều.

    Sau đó agent dịch kết quả thành câu chữ rồi mới đưa vào prompt. Ví dụ: “Giá đang nằm trên SMA 200 và đường này đang dốc lên: xu hướng tăng còn vững.”

    Máy tính lo số học, LLM lo đọc hiểu, mỗi bên làm đúng việc mình giỏi. Với giá thô, LLM chỉ nhận 14 đến 30 ngày gần nhất, đủ để thấy nhịp ngắn hạn.

3. Rút kinh nghiệm theo cả chu kỳ, không theo từng lệnh #

Làm sao để AI rút kinh nghiệm? Mô hình không được huấn luyện lại; bản tổng kết cũ chỉ được đưa vào prompt ở những lần phân tích sau.

Cách đầu tiên nghĩ tới là bắt AI đọc lại từng lệnh. Nhưng trong chiến lược DCA, một lệnh 5 đô bị lỗ hôm qua gần như không nói lên gì: nhiễu nhiều hơn tín hiệu. Săm soi từng lệnh như vậy còn tốn tiền API, vì mỗi lần gọi LLM là trả tiền theo lượng chữ gửi đi và nhận về.

Như người mua vàng mỗi tháng: lần mua đúng hôm giá cao nhìn riêng thì lỗ, nhưng điều đáng hỏi là giá vốn trung bình của cả đợt.

  • Tùy biến của tôi: đánh giá theo cả chu kỳ, tức cả đợt mua gắn với một xu hướng giá.

    Tầng thực thi tính giá vốn trung bình của cả chu kỳ, thường kéo dài nhiều ngày. Khi xu hướng đảo chiều, nó gửi lại cho AI một bản tổng kết có dạng như sau (số liệu minh họa): “Chu kỳ tăng tháng 5 kết thúc, giá vốn trung bình 2.650 USD, lợi nhuận ròng +1,8%.” Ở mức tổng kết này mới có quy luật để nhận ra.

4. Đừng tin con số tự tin của AI #

Có nên để AI tự quyết số tiền mỗi lệnh, từ 5 đến 10 đô, theo mức “tự tin” nó tự báo không? Câu trả lời từ các nghiên cứu: không.

LLM tự đánh giá độ chắc chắn của mình rất kém. Mô hình được huấn luyện để trả lời nghe quả quyết, nên nó có thể báo “tự tin 99%” ngay cả khi đang bịa. Để nó tự quyết số tiền thì sớm muộn sẽ có ngày nó dồn tiền nhiều nhất vào đúng lệnh sai.

  • Tùy biến của tôi: giữ kỷ luật DCA cố định ở tầng thực thi. Số tiền mỗi lệnh do một quy tắc cố định trong code quyết định, và AI không có quyền đổi.

5. Cho AI tranh luận quá hai vòng là chúng bắt đầu gật gù #

Ban đầu tôi tưởng cứ cho nhiều AI vào một phòng chat cãi nhau càng lâu thì càng ra chân lý. Thực tế, các nghiên cứu cho thấy qua vòng thứ hai, chúng bắt đầu hùa theo nhau.

Lý do nằm ở cách huấn luyện: mô hình được dạy để đồng thuận và giữ cuộc trò chuyện êm đẹp. Vì vậy bên này nhượng bộ bên kia dần dần, hoặc cả hai lặp lại cùng một ý bằng chữ khác.

  • Tùy biến của tôi: ép cuộc tranh luận vào đúng hai vòng.
    • Vòng 1 (bịt mắt): hai phe bị tách riêng, mỗi bên viết báo cáo mà không thấy bài bên kia. Ai đọc ý người khác trước thường viết xoay quanh ý đó, hiện tượng gọi là hiệu ứng mỏ neo. Cách ly là để tránh nó.
    • Vòng 2 (đối chất): mỗi bên chỉ được chỉ ra một lỗ hổng logic của bên kia, cấm lặp lại nội dung vòng một.
    • Khi hòa: nếu dữ liệu quá nhiễu và không bên nào thắng, quản lý nghiên cứu không được cưa đôi kết quả. Nó phải áp quy tắc phá hòa viết sẵn: hoặc kéo mức chốt lời lại gần hơn vì thị trường đang rủi ro, hoặc đi theo hướng của SMA 200.

Cả năm điều cùng nói một ý: có những việc không nên để LLM làm. Mục sau là hàng rào tôi dựng để nó không làm được.

III. Kiến trúc: AI viết khuyến nghị, code giữ tiền #

Làm một thời gian, tôi rút ra một điều: không bao giờ giao quyền cầm tiền cho một hệ thống chạy bằng xác suất. LLM chọn từng chữ tiếp theo theo xác suất, nên cùng một câu hỏi có thể ra hai câu trả lời khác nhau. Cách duy nhất là nhốt phần bất định đó bên trong code thường. Code thường ở đây là code do người viết từng dòng, cùng đầu vào thì luôn ra cùng kết quả.

Như bản gốc, dự án có 5 bước với 12 agent, và tôi sửa lại từng agent để chạy thật.

Cả hệ thống tách làm hai nửa độc lập: AI Brain lo phân tích, Execution Hands lo đặt lệnh. Đây là điểm quan trọng nhất của bài: phần AI không bao giờ chạm được vào tiền. Nghĩ lại câu chuyện người mua vàng tích lũy: nghe bạn bè bàn giá lên xuống có thể làm họ chần chừ một tháng. Nhưng số tiền dành dụm đã chốt sẵn, và không người bạn nào được phép cầm thẻ ATM của họ.

1. AI Brain: 5 bước, 12 agent #

Thay vì viết một prompt dài thò lò rồi ngồi cầu nguyện, tôi dùng LangGraph để điều phối các agent. LangGraph là một thư viện để ghép nhiều bước gọi LLM thành một quy trình dạng sơ đồ. Mỗi node trên sơ đồ là một việc, còn đường đi giữa các node là code thường do tôi viết, không phải do mô hình tự chọn. Mô hình chỉ được tự do bên trong từng node.

Bước 1 — Gom dữ liệu. Bốn agent chạy nối tiếp:

  • Market Analyst: lấy dữ liệu giá bằng yfinance và tính chỉ báo kỹ thuật bằng stockstats, như Mục II.2.

  • News Analyst: lấy tin kinh tế toàn cảnh, tức tin về lãi suất, lạm phát, chính sách của các ngân hàng trung ương. Nó lọc nhiễu và chỉ giữ những sự kiện có thể tạo xu hướng trong 1 đến 4 tuần.

  • Social Analyst: đo tâm lý đám đông để đoán nhà đầu tư nhỏ lẻ đang muốn mua hay bán. Nó theo dõi chỉ số sợ hãi và tham lam, đo biến động giá cùng độ sôi động của các cuộc bàn tán. Ngoài ra, nó quét thảo luận trên StockTwits, mạng xã hội của giới đầu tư.

  • Fundamentals Analyst: lấy các chỉ số doanh nghiệp như P/E, PEG, ROE, dựa trên báo cáo tài chính, để xem tài sản đang rẻ hay đắt so với giá trị thật.

    Tôi vẫn code node này để giữ nguyên kiến trúc của tác giả gốc. Nhưng vàng token hóa không phải doanh nghiệp, không có báo cáo tài chính, nên với XAUT tôi bỏ qua node này.

Bước 2 — Tranh luận. Hai vòng như Mục II.5: hai phe viết độc lập từ dữ liệu bước 1, rồi đối chất để tìm lỗ hổng logic hoặc chỗ đọc sai dữ liệu của nhau. Cuối cùng, quản lý nghiên cứu gom những lập luận chắc nhất thành một báo cáo trung lập, làm la bàn cho bước ra quyết định.

Bước 3 — Lên kế hoạch. Từ báo cáo đó, agent Trader đề xuất một kế hoạch cụ thể: điểm vào lệnh, mức cắt lỗ, mức chốt lời. Điểm vào lệnh là mức giá định mua. Cắt lỗ là tự bán khi giá giảm tới một mức đặt trước, để khoản lỗ không lớn thêm. Các mức này tính theo biên độ dao động thật của giá, không phải một tín hiệu chung chung kiểu “nên mua”.

Bước 4 — Quản trị rủi ro. Ba agent soi kế hoạch với ba khẩu vị khác nhau: một bên chuộng lợi nhuận, một bên chuộng giữ vốn, một bên đứng giữa. Nếu ba bên xung đột, hoặc kế hoạch có dấu hiệu dồn vốn bất thường, agent Portfolio Manager chỉnh lại quy mô lệnh hoặc hủy hẳn.

Bước 5 — Lưu kết quả. AI Brain hoàn toàn không biết số dư thật trong ví trên sàn. Việc cuối cùng của Portfolio Manager chỉ là ghi vào database một file JSON chứa đúng một quyết định: LÊN, XUỐNG hoặc ĐỨNG NGOÀI, kèm ghi chú giải thích. JSON là định dạng dữ liệu dạng chữ mà phần mềm nào cũng đọc được. Hết. Không có đường nào từ đây đi thẳng ra sàn.

2. Execution Hands: code thường giữ tiền #

Nửa này là một chương trình Python viết hoàn toàn bằng code thường, kết nối với Binance, một sàn tiền mã hóa lớn. Nó giữ API key, tức chuỗi mã bí mật cho phép phần mềm đặt lệnh thay chủ tài khoản. Nó đọc file JSON từ AI Brain rồi tự quyết có gửi lệnh lên sàn hay không.

Trái tim của nó là một cầu dao tự động, giống cầu dao điện trong nhà: vượt ngưỡng là ngắt, và chỉ bật lại bằng tay. Bất kể AI tự tin đến đâu, nếu tổng tài sản tụt quá 15% so với mức cao nhất từng đạt, cầu dao ngắt. Mọi giao dịch dừng ngay lập tức cho tới khi có người vào xem lại. Giả sử tài khoản từng lên 1.000 đô: xuống dưới 850 đô là cầu dao ngắt.

Đây là điểm mấu chốt: code thường dùng logic cứng để giữ phần AI trong vòng kiểm soát. AI được phép sai, và chắc chắn sẽ sai. Nhưng sai tới đâu thì đã bị chặn bằng một con số trong code, không phụ thuộc hôm đó mô hình viết ra gì.

Thú thật, tầng thực thi này tôi chưa đào sâu; mọi thứ đang ở mức cơ bản nhất đủ để an toàn. Chắc phải đợi hôm nào nằm mơ thấy ông Bụt hiện lên cho một thiết kế tốt hơn, tôi mới viết lại phần này.

IV. Báo cáo nghe hợp lý chưa phải là có lãi #

Đọc các bản báo cáo hằng ngày dàn agent này xuất ra, tôi thấy lập luận chắc chắn, đáng tin. Nếu tự tôi ngồi xem biểu đồ giá và đọc tin tức kinh tế tổng thể, có lẽ kết luận cũng chẳng khác bao nhiêu. Nghe thì mừng, nhưng nghĩ kỹ thì điều đó chỉ chứng minh AI lập luận giống tôi, chưa chứng minh cách lập luận đó kiếm ra tiền.

Nên cần nói thẳng: “báo cáo đọc thấy hợp lý” và “chiến lược có lãi” là hai chuyện khác nhau, và cái thứ nhất không chứng minh được cái thứ hai. Hệ thống vẫn đang chạy thử. Thị trường luôn có những cú bất ngờ, nhất là trượt giá.

Trượt giá là khi giá khớp lệnh thật lệch khỏi giá bạn thấy lúc đặt lệnh, hay gặp khi ít người mua bán hoặc giá chạy quá nhanh. Chỉ thời gian mới trả lời được hệ thống này lãi hay lỗ. Và bài này là nhật ký kỹ thuật, không phải lời khuyên đầu tư.

Dù lãi lỗ ra sao, dự án cho tôi một kết luận rõ ràng: ráp AI vào sản phẩm cần vạch ranh giới, thay vì ném mọi thứ vào một prompt rồi chờ đợi. Các khối code thường, gồm sơ đồ luồng, cầu dao và tầng lấy dữ liệu, giữ và dẫn hướng phần chạy bằng xác suất, buộc nó làm việc có kỷ luật. Phần AI lo đọc hiểu; phần code lo không để mất tiền.

Nếu đang đưa AI vào sản phẩm, hãy hỏi đội kỹ thuật một câu: “Nếu AI trả lời sai hoàn toàn, code nào chặn nó lại và thiệt hại tối đa là bao nhiêu?” Ở MdevTrade, câu trả lời là cầu dao và con số 15% tính từ mức cao nhất.

Mã nguồn toàn bộ dự án được công khai tại: https://github.com/vinhmdev-com/mdevtrade

Đặc biệt cảm ơn tác giả dự án gốc TradingAgents tại https://github.com/TauricResearch/TradingAgents vì nguồn cảm hứng và ý tưởng kiến trúc tuyệt vời.