Hướng dẫn dưới đây trích từ sách HDSD Amibroker phiên bản 6.9 bản Tiếng Việt do team Ami X biên dịch. Để tìm đọc đầy đủ tải bản PDF full tại: HDSD Amibroker
Pyramiding / Scaling
Hai hằng số đặc biệt: sigScaleIn / sigScaleOut được thêm vào để cung cấp phương tiện cho backtester biết khi nào bạn muốn scale-in/out
Tất cả những gì bạn phải làm để triển khai pyraminding là:
– Gán sigScaleIn cho biến BUY/SHORT nếu bạn muốn scale-in (tăng kích thước của) vị thế LONG/SHORT
– Gán sigScaleOut cho biến BUY/SHORT nếu bạn muốn scale-out (giảm kích thước của) vị thế LONG/SHORT
Kích thước scaleing được xác định bởi biến PositionSize, trong trường hợp scaleing, biến này không xác định kích thước vị thế tuyệt đối mà là tăng hoặc giảm đô la.
QUAN TRỌNG: Xin lưu ý rằng backtester coi giao dịch mà bạn scale-in/out là giao dịch DUY NHẤT (tức là sẽ hiển thị một hàng trong danh sách giao dịch). Sự khác biệt duy nhất so với giao dịch thông thường là nó sẽ tính giá nhập trung bình (và tỷ giá hối đoái nhập trung bình) dựa trên tất cả các mục nhập một phần và giá thoát trung bình (và tỷ giá hối đoái thoát trung bình) dựa trên tất cả các mục nhập/thoát ngang giá và sẽ hiển thị giá trung bình trong trường giá nhập/thoát. Tất nhiên, hoa hồng được áp dụng chính xác cho mỗi mục nhập/thoát (một phần) tùy thuộc vào quy mô mua/bán một phần.
Nếu bạn muốn xem chi tiết về việc mở rộng quy mô, bạn phải chạy thử nghiệm ngược ở chế độ “NHẬT KÝ CHI TIẾT” vì chỉ khi đó bạn mới thấy cách mở rộng quy mô hoạt động như thế nào và giá trung bình được tính như thế nào.
Cũng lưu ý rằng hỗ trợ mở rộng quy mô và nhiều loại tiền tệ chỉ khả dụng trong trình kiểm tra ngược danh mục đầu tư. Trình kiểm tra ngược cũ cũng như hàm Equity() KHÔNG xử lý việc mở rộng quy mô hoặc nhiều loại tiền tệ (chúng chỉ bỏ qua các lệnh mở rộng quy mô).
Ví dụ dễ hiểu:
Ví dụ 1: trung bình chi phí đô la (mỗi tháng bạn mua cổ phiếu với số tiền cố định)
FixedDollarAmount = 500;
MonthBegin = Month() != Ref( Month(), -1); FirstPurchase = Cum( MonthBegin) == 1;
Buy = IIf( FirstPurchase, 1, // True (hoặc 1) biểu thị tín hiệu mua thông thường IIf( MonthBegin, sigScaleIn, // mỗi tháng tăng vị thế
0) ); // nếu không thì không có tín hiệu
Sell = 0; // chúng tôi không bán
PositionSize = FixedDollarAmount;
Ví dụ 2: trung bình chi phí đô la
(công thức đơn giản hóa vì AB coi sigScaleIn đầu tiên là mua)
FixedDollarAmount = 500;
MonthBegin = Month() != Ref( Month(), -1); FirstPurchase = Cum( MonthBegin) == 1;
Buy = IIf( MonthBegin, sigScaleIn, 0); // mỗi tháng tăng vị thế
Bán = 0; // chúng tôi không bán
PositionSize = FixedDollarAmount;
Ví dụ 3: tăng vị thế khi lợi nhuận tạo ra từ giao dịch không có kim tự tháp trở nên lớn hơn 5% và giảm vị thế khi thua lỗ lớn hơn -5%
// ngưỡng thay đổi vốn chủ sở hữu phần trăm khi thực hiện kim tự tháp PyramidThreshold = 5;
// các quy tắc giao dịch thông thường (không có kim tự tháp)
Mua = Cross( MACD(), Signal() );
Bán = Cross( Signal(), MACD() );
e = Equity(1); // tạo vốn chủ sở hữu mà không có hiệu ứng kim tự tháp PcntProfit = 100 * ( e – ValueWhen( Buy, e ) )/ValueWhen( Buy, e ); InTrade = Flip( Buy, Sell );
// ExRem được sử dụng ở đây để đảm bảo rằng việc mở rộng quy mô xảy ra
// chỉ một lần kể từ khi tham gia giao dịch
DoScaleIn = ExRem( InTrade AND PcntProfit > PyramidThreshold, Sell ); DoScaleOut = ExRem( InTrade AND PcntProfit < -PyramidThreshold, Sell );
// sửa đổi các quy tắc để xử lý kim tự tháp
Buy = Buy + sigScaleIn * DoScaleIn + sigScaleOut * DoScaleOut;
PositionSize = IIf( DoScaleOut, 500, 1000 ); // nhập và mở rộng kích thước $1000, mở rộng kích thước: $500
Ví dụ 4: thoát một phần (mở rộng) khi dừng mục tiêu lợi nhuận
Ví dụ về mã thoát 50% ở mục tiêu lợi nhuận đầu tiên, 50% ở mục tiêu lợi nhuận tiếp theo và mọi thứ ở điểm dừng theo sau:
Buy = Cross( MA( C, 10 ), MA( C, 50 ) );
Sell = 0;
// hệ thống sẽ thoát
// 50% vị thế nếu lệnh dừng MỤC TIÊU LỢI NHUẬN ĐẦU TIÊN bị chạm
// 50% vị thế là lệnh dừng MỤC TIÊU LỢI NHUẬN THỨ HAI bị chạm
// 100% vị thế nếu lệnh DỪNG THEO DÕI bị chạm
FirstProfitTarget = 10; // lợi nhuận SecondProfitTarget = 20; // theo phần trăm TrailingStop = 10; // cũng theo phần trăm
priceatbuy=0; highsincebuy = 0;
exit = 0;
for( i = 0; i < BarCount; i++ )
{
if( priceatbuy == 0 AND Buy[ i ] )
{
priceatbuy = BuyPrice[ i ];
}
if( priceatbuy > 0 )
{
highsincebuy = Max( High[ i ], highsincebuy );
if( exit == 0 AND
High[ i ] >= ( 1 + FirstProfitTarget * 0.01 ) * priceatbuy )
{
// mục tiêu lợi nhuận đầu tiên đạt được – scale-out exit = 1;
Buy[ i ] = sigScaleOut;
}
if( exit == 1 AND
High[ i ] >= ( 1 + SecondProfitTarget * 0.01 ) * priceatbuy )
{
// mục tiêu lợi nhuận thứ hai đạt được – exit exit = 2;
SellPrice[ i ] = Max( Open[ i ], ( 1 + SecondProfitTarget * 0.01 ) *
priceatbuy );
}
if( Low[ i ] <= ( 1 – TrailingStop * 0.01 ) * highsincebuy )
{
// trailing stop hit – exit exit = 3;
SellPrice[ i ] = Min( Open[ i ], ( 1 – TrailingStop * 0.01 ) * highsincebuy );
}
if( exit >= 2 )
{
Buy[ i ] = 0;
Sell[ i ] = exit + 1; // đánh dấu mã thoát thích hợp exit = 0;
priceatbuy = 0; // đặt lại giá highsincebuy = 0;
}
}
}
SetPositionSize( 50, spsPercentOfEquity );
SetPositionSize( 50, spsPercentOfPosition * ( Buy == sigScaleOut ) ); // mở rộng 50% vị thế