Chúng tôi sẽ định lượng các phương pháp giao dịch sử dụng đường MA qua bài viết này. dữ liệu bao gồm toàn bộ các cổ phiếu ở sàn HOSE từ 2018 đến bây giờ. Chúng tôi sẽ tìm ra các điểm mua, bán trong bộ dữ liệu trên, qua đó nghiên cứu xác suất, lợi nhuận để kiểm tra các phương pháp giao dịch sử dụng đường MA có còn hiệu quả hay không
Phương pháp giao dịch sử dụng đường MA thường xem đường MA là các ngưỡng kháng cự, hỗ trợ
Chúng tôi sẽ định lượng 3 đường MA là SMA, WMA, EMA, trong các khoảng thời gian ngắn hạn 20 ngày, trung hạn 50 ngày, và dài hạn 200 ngày
Chúng tôi sử dụng python trên môi trường google colab và các thư viện talib, numpy, pandas để làm thống kê. Để cài thư viện talib chúng tôi chạy các dòng lệnh sau, thư viện numpy, pandas, matplotlib đã có sẵn trên môi trường google colab
url = 'https://anaconda.org/conda-forge/libta-lib/0.4.0/download/linux-64/libta-lib-0.4.0-h166bdaf_1.tar.bz2'
!curl -L $url | tar xj -C /usr/lib/x86_64-linux-gnu/ lib --strip-components=1
url = 'https://anaconda.org/conda-forge/ta-lib/0.4.19/download/linux-64/ta-lib-0.4.19-py310hde88566_4.tar.bz2'
!curl -L $url | tar xj -C /usr/local/lib/python3.10/dist-packages/ lib/python3.10/site-packages/talib --strip-components=3
Sau đó import các thư viện cần thiết
import talib
import numpy as np
import pandas as pd
import os
Dữ liệu giá của tất cả các mã cổ phiếu ở sàn HOSE từ ngày đầu được chúng tôi thu thập và nén lại có thể được download tại đây. Chúng tôi dùng đoạn code sau để tải dữ liệu về, giải nén, và đọc dữ liệu
! wget -O data.zip https://github.com/tranphuminhbkhn/MTQuant/raw/refs/heads/main/data.zip
! unzip data.zip
data = {}
for fn in os.listdir('data'):
symbol = fn[:-4]
if len(symbol) != 3 and symbol != 'VNINDEX':
continue
data[symbol] = pd.read_csv('data/{}'.format(fn))
Sử dụng thư viện talib để tính toán các đường MA cho từng mã cổ phiếu như sau
SMA = {}; WMA = {}; EMA = {}; ncandle = 20
for symbol in data:
sma = talib.SMA(np.array(data[symbol]['Close']), ncandle)
wma = talib.WMA(np.array(data[symbol]['Close']), ncandle)
ema = talib.EMA(np.array(data[symbol]['Close']), ncandle)
SMA[symbol] = sma; WMA[symbol] = wma; EMA[symbol] = ema
Sau đó chúng tôi sẽ trích xuất các giá trị cần thiết để tính toán theo mã cổ phiếu và ngày, Chúng tôi giả sử sẽ mua / bán được giá ATC trong phiên mà xuất hiện tín hiệu
DATA = {}
for symbol in data:
DATA[symbol] = {}
for i in range(ncandle, len(SMA[symbol])):
dt = data[symbol]['Date'][i]
if dt < 180000:
continue
c = data[symbol]['Close'][i]
sma = SMA[symbol][i]; wma = WMA[symbol][i]; ema = EMA[symbol][i]
DATA[symbol][dt] = [c, sma, wma, ema]
Phương pháp này xem đường MA như là hỗ trợ, kháng cự, khi giá cắt và vượt lên trên đường MA là break kháng cự và sẽ có tín hiệu mua, ngược lại khi giá cắt xuống đường MA, nghĩa là gãy vùng hỗ trợ và cho tín hiệu bán
price = data_[dt][0]; sma = data_[dt][1]
if sma > price and not inOrder_flag:
bprice = price # Mua tại giá đóng cửa
bvniprice = vprice
n = 0; inOrder_flag = True; order = [dt]
if sma < price and inOrder_flag and n >= 2: # Phải sau 2 ngày mới có thể bán
sprice = price # Bán tại giá đóng cửa
svniprice = vprice
profit = sprice / bprice - 1
inOrder_flag = False; order.append(dt); order_data[symbol].append(order)
order_profit.append(profit)
vni_change.append(svniprice / bvniprice - 1)
nhold.append(n)
Nhìn qua quả định lượng, lợi nhuận có thể đạt tầm 15% mỗi năm. Nhưng sau khi chúng tôi đảo ngược tín hiệu mua bán của hệ thống, mua khi đường giá cắt xuống dướng đường MA và bán khi Giá cắt lên trên, thì lợi nhuận đạt 0.7341% sau thời gian nắm giữ trung bình là 8.82 ngày, có thể thấy phương pháp giao dịch này không hiệu quả trên dữ liệu thị trường chứng khoán Việt Nam. Tiếp theo chúng tôi sẽ phân tích nếu không phụ thuộc vào thị trường thì kết quả định lượng sẽ thế nào
Chúng tôi giả sử có thể giao dịch cổ phiếu ở cả 2 chiều LONG và SHORT, Long khi giá cắt và vượt lên SMA20 và SHORT khi giá cắt xuống SMA20. Khi đó có thể đánh giá tổng quan sự hiệu quả của phương pháp mà không bị ảnh hưởng bởi thị trường
if price < sma: # SHORT
if inOrder_flag == 'LONG' and n >= 2:
# Đóng vị thế LONG
sprice = price # Mua tại giá đóng cửa
order_profit.append(sprice / bprice - 1)
order.append(dt); order_data[symbol].append(order)
inOrder_flag = 'None'; nhold.append(n)
if inOrder_flag == 'None':
# Mở vị thế SHORT
bprice = price; n = 0; inOrder_flag = 'SHORT'; order = [dt]
if price > sma: # LONG
if inOrder_flag == 'SHORT' and n >= 2:
# Đóng vị thế SHORT
sprice = price # Mua tại giá đóng cửa
order_profit.append(1 - sprice / bprice)
order.append(dt); order_data[symbol].append(order)
inOrder_flag = 'None'; nhold.append(n)
if inOrder_flag == 'None':
# Mở vị thế LONG
bprice = price; n = 0; inOrder_flag = 'LONG'; order = [dt]
Kết quả được thể hiện ở bảng sau
Ngắn hạn | Trung hạn | Dài hạn | |||||||
---|---|---|---|---|---|---|---|---|---|
SMA-20 | WMA-20 | EMA-20 | SMA-50 | WMA-50 | EMA-50 | SMA-200 | WMA-200 | EMA-200 | |
Số lần vào lệnh | 72333 | 89414 | 78066 | 45069 | 57672 | 50788 | 20520 | 27211 | 23326 |
Thời gian nắm giữ | 9.12 ngày | 7.38 ngày | 8.44 ngày | 14.43 ngày | 11.35 ngày | 12.79 ngày | 29.47 ngày | 22.82 ngày | 26.03 ngày |
Lợi nhuận trung bình | -0.0818% | -0.0998% | -0.1137% | -0.0668% | -0.098% | -0.146% | 0.492% | 0.2845% | 0.2679% |
Nhìn bảng kết quả trên chúng ta có thể thấy
Vì các đường MA là các chỉ báo vận động khá chậm so với giá, nên khi so sánh hai đường MA thì nó biến động rất chậm, trong nghiên cứu này, chúng tôi so sánh MA10 và MA20 để xác định xu hướng trung hạn, MA20 và MA50 cho xu hướng dài hạn. Kết quả như sau
Trung hạn | Dài hạn | |||||
---|---|---|---|---|---|---|
SMA10 & SMA20 | WMA10 & WMA20 | EMA10 & EMA20 | SMA20 & SMA50 | WMA20 & WMA50 | EMA20 & EMA50 | |
Số lần vào lệnh | 37351 | 41289 | 29221 | 15070 | 17924 | 12591 |
Thời gian nắm giữ | 17.59 ngày | 15.91 ngày | 22.25 ngày | 42.81 ngày | 36.17 ngày | 50.35 ngày |
Lợi nhuận trung bình | 0.6568% | 0.3114% | 0.4135% | 1.3573% | 1.276% | 1.9823% |
Trong các phần trên chúng tôi đã làm thống kê định lượng các phương pháp giao dịch sử dụng đường MA bao gồm:
Trong từng phương pháp chúng tôi làm các thí nghiệm riêng rẻ với các loại đường MA khác nhau (SMA, WMA, EMA) và với các khung thời gian khác nhau. Phương pháp tín hiệu khi các đường MA cắt nhau là một phương pháp đơn giản và là một phương pháp hiếm hoi có thể đem lại hiệu quả trong thị trường chứng khoán Việt Nam. Các chỉ báo MA về dài hạn thể hiện xu hướng tương đối tốt, và rất khó để có thể bị "vẽ"
Mọi nghiên cứu phía trên chúng tôi thực hiện trên môi trường google colab, bấm vào để xem vào thực thi đoạn code