Tải bản đầy đủ

AMIBROKER hoc code

AMIBROKER: AFL HOẠT ĐỘNG
NHƯ THẾ NÀO (1)?
1 Giới thiệu khái quát
Amibroker theo developer Tomasz Janeczko được xây dựng dựa trên ngôn
ngữ C. Vì vậy bộ code Amibroker Formula Language sử dụng có syntax khá
tương đồng với C, ví dụ như câu lệnh #include để import hay cách gói các
object, hàm trong các block {} và kết thúc câu lệnh bằng dấu “;”.
Bản thân ngôn ngữ AFL tự định nghĩa:
1.
2.

Syntax
Các toán tử cơ bản (như cộng trừ nhân chia….) và ưu tiên làm việc trên
các loại data nguyên thủy (scalar, float)
3.
Control Flow (Conditional execution hay Loop)
4.
Các khía niệm về cấu trúc (Biến, hàm, thủ tục, cấu trúc, đối tượng)
5.
1 số công cụ khác như xử lý ngoại lệ….
Amibroker không phải là một mã nguồn mở (open source) như Python, R hay

C++, vì vây các thư viện trong Amibroker chỉ có thể được cung cấp bới
1.
2.
3.
4.

#include – import các library viết trước dưới dạng “.afl”
Amibroker Development kit
Jscript/VBscript
External COM object (cái này không hiểu
lắm) http://www.amibroker.com/guide/a_aflcom.html
Ngoài ra người dùng có thể share các indicators lên forum của amibroker cho
người khác dùng lại. Tuy nhiên customized indicators cho profit ngon thì
thường bị exploited rất nhanh nên đến lúc up lên dc forum hay database thì
profit cũng giảm mất rồi.
So với các package numpy/pandas trên Python hay nguồn package đồ sộ
trên R-forge thì các operation cho ma trận trên amibroker (các ngôn ngữ như
C hay Java sơ khai cũng không hỗ trợ các operation cho ma trận) khó thực
hiện hơn nhiều. Thế nên khi search các articles trên các website về portfolio
analysis, các đoạn code cho python hay r thường dễ tìm và có sẵn hơn
Thế sao mọi người đơn giản không sử dụng Python hay R. Đầu tiên Amibroker
có GUI, thân thiện hơn với người nào không biết code. Thứ 2 là paramters
cho các indicators cũng có GUI luôn. Thứ 3 là bộ automatic analysis kết hợp
với control flow cũng thực hiện được khá nhiều thứ hay ho cho backtesting
và optimization. Và cuối cùng là nếu mất tiền thì bản thân các developer của
Amibroker cũng cung cấp các đoạn code cho các customized indicators nếu
khách hàng yêu cầu và trả phí bản quyền đầy đủ. Một yếu tố khá quan trọng


nữa là yếu tố đầu vào cho database. Không phải ở đâu database cũng
support R, Python và không phải ở đâu cũng có sẵn data để import vào
Amibroker.
Với ai theo trường phái kiểu Pure Technician thì sẽ không phân biệt được giữ
Metastock và Amibroker khác nhau gì ngoài việc chart của Amibroker đẹp
hơn 1 chút nếu so với MS bản dưới 11 :LOL:
Ở khía cạnh quan trọng nhất, có thể hiểu AFL trong Amibroker là ngôn ngữ
xử lý mảng (an array processing language). Nó hoạt động dựa trên các mảng
(các dòng/vector) số liệu, khá giống với cách hoạt động của spreadsheet trên
excel.
Mảng (array) đơn giản là một tập hợp (1 hàng) các số liệu, cũng có thể hiểu


nó là các vector. Amibroker lưu trong cơ sở dữ liệu mỗi cổ phiếu 6 mảng bao
gồm: Giá mở cửa (opening price), giá đóng cửa (closing price), giá cao (high),
giá thấp (low), khối lượng (volume) và các hợp đồng đang ở dạng open (open
interest, không áp dụng cho dữ liệu cổ phiếu). Ví dụ dưới minh họa cách AFL
lưu dữ liệu trong mảng :

Bất kì 1 mảng nào khác đều được tính toán dựa trên các toán tử và công thức
xây dựng sẵn trong thư viện AFL từ 6 mảng cơ bản trong cơ sở dữ liệu của
mỗi cổ phiếu. Mỗi giá trị trong 1 mảng đều có 1 giá trị ngày tháng tương ứng
với nó.
2. Xử lý mảng và tốc độ của AFL
Giả sử có câu lệnh: MyVariable = (High + Low) / 2
Khi AFL đánh giá 1 câu lệnh trên, đầu tiên nó lấy 2 mảng High và Low từ cơ
sở dữ liệu của cổ phiếu, sau đó thêm các mảng tương ứng. Nói 1 cách
khác,bước đầu tiên, toán tử “+” (và có thể áp dụng với các toán tử khác)
được xử lý để tạo ra một mảng khác, sau đó mảng mới sẽ tiếp tục được áp
dụng toán tử “/” ở bước tiếp theo và được gán cho biến MyVariable.


3. Trung bình trượt (Moving Averages), và câu lệnh điều kiện
(Conditional Statements)
Có đoạn code:
1
Cond1 = Close > MA (Close, 3);
Cond2 = Volume > Ref (Volume, -1);
2
Buy = Cond1 and Cond2;
3
Sell = High > 1.3;
4
Đoạn code trên tạo ra tín hiệu mua khi giá đóng cửa ngày hôm nay lớn hơn
đường MA(3) và khối lượng ngày áp dụng lớn hơn khối lượng ngày trước đó.
Nó cũng tạo ra tín hiệu bán khi giá cao nhất trong ngày áp dụng lớn hơn
1.30.
Nếu trong đoạn code, người dùng cần xem xét giả thiết giá đóng cửa lớn hơn
giá trị MA(3), AFL đầu tiên sẽ quét mảng close price và tạo ra một mảng mới
MA(close, 3) cho mỗi cổ phiếu cần phân tích. Mỗi ô giá trị (cell) trong mảng
mới sẽ được so sánh với mảng close price. Từ kết quả so sánh, AFL lại tạo ra
một mảng mới, có tên Cond1, nếu close price lớn hơn giá trị MA(close,3)
tương ứng, ô giá trị tương ứng trong mảng Cond1 được gán giá trị 1. Nếu
close price nhỏ hơn MA(close,3), ô giá trị tương ứng trong mảng Cond1 được
gán giá trị 0.
AFL có thể nhìn về cả 2 phía mỗi ô giá trị trong chuỗi thời gian, bằng cách sử
dụng hàm Ref. Tương tự như trên, lần lượt mảng Ref(Volume, -1) và mảng
Cond2 được tạo ra từ database gốc. Sau đó mảng Buy và mảng Sell lần lượt
được thiết lập, chi tiết như sau:

Buy và Sell là 2 mảng đặc biệt, khi tạo biến với tên “Buy” và “Sell”, AFL
ngầm hiểu đó là tín hiệu để mua và bán.
4. Hàm plot() trong Amibroker


1
plot(array, name, color, style = styleLine,
minvalue = Null, maxvalue = Null,
2
XShift = 0, ZOrder = 0, width = 1)
3
4 tham số quan trọng nhất bao gồm:





Tham số array đại diện cho số liệu sẽ được vẽ
Tham số name đại diện cho tên của đồ thị
Tham số color dùng để thể hiện màu sắc cho đồ thị
Tham số style định nghĩa dạng đồ thị được vẽ
(line/histogram/candlestick/bar, etc….)
Plot(RSI(16), "Draft RSI", colorBlueGrey);
1
Câu lệnh trên khi apply cho chart như hình bên dưới:



Tham số Zorder được dùng để tạo các layer cho object cần được vẽ,
value sẽ tương ứng như sau:



Tham số Zshift phức tạp hơn một chút. Lấy 1 ví dụ cụ thể, tạo 1 chart
từ dữ liệu close price kết hợp với đường MA(15) như đoạn code bên dưới:
1
Plot(Close, "Adjusted Close", colorDefault, styleBar);
Plot(MA(Close, 15), "MA-15", colorRed, styledashed);
2
Plot(MA(Close, 15), "MA-Shift", colorBlue, styleThick, Null, Null, 10);
3


Ta được đồ thị như hình, cụ thể tham số Zshift có tác dụng shift object sang
phải hoặc sang trái = số bar đã input, ở trường hợp này là 10.
Một điểm khá hay cần lưu ý đó là khả năng thay đổi màu sắc (Dynamic Color)
khi các object (indicator, price,…) thỏa mãn một số điều kiện cho trước (sử
dụng hàm Iff )
1
2

dynamic_color = IIf(MACD() > 0 , colorBlue, colorRed);
Plot(MACD(), "My MACD", dynamic_color, styleHistogram | styleThick)

Có thể kết hợp nhiều style vào trong một chart dựa vào kí hiệu “|”, chi tiết về
các style cụ thể có thể tìm ở trên website của Amibroker.
Một điểm rất hay khi sử dụng chart trong Amibroker đó là có thể thay đổi giá
trị của đối số cho 1 một tham số trong một hàm. Giả sử thay vì cố định giá trị
MA(16) với màu sắc, title và tên như ở phía trên, có thể tạo nên một vector
các đối sốbằng các câu lệnh: Param, ParamStr, Paramcolor, Paramstyle, sau
đó pass vector vào hàm. Ưu điểm ở chỗ có thể tùy chỉnh giá trị tham số ngay
trên đồ thị. Phía dưới là 1 ví dụ đơn giản nhất có thể làm được.


1
2
3

period = Param("MA1", 16, 3, 50, 1);
Plot(MA(Close,period), "Simple Moving Average (" + period + ")", colorBrown,
stylethick);

Phía dưới là 1 ví dụ khác lấy từ thư viện AFL knowledge base:
1
2
3
4
5
6

ticker = ParamStr( "Ticker", "VNINDEX" );
sp = Param( "MA Period", 12, 2, 100 );
PlotForeign( ticker, "Chart of "+ticker,
ParamColor( "Price Color", colorBlack ), styleCandle );
Plot( MA( Foreign( ticker, "C" ), sp ), "MA",
ParamColor( "MA Color", colorRed ) );


AMIBROKER: AFL HOẠT ĐỘNG
NHƯ THẾ NÀO (2) – SCAN VÀ
EXPLORATION

Sau khi hiểu được nguyên lý hoạt động của Amibroker dựa trên nguyên lý
vectorization (tính toán dựa trên các mảng có sẵn như OHLC hay volume), ở
bài viết này tôi sẽ phân tích về chức năng Scan và Exploration trong
Amibroker.
Một trong những tính năng mạnh nhất của Amibroker là khả năng quét
(screen) hàng trăm cổ phiếu trong thời gian thực (real-time) và theo dõi tín
hiệu giao dịch tương ứng. Việc quét này được thực hiện bởi chức năng “Scan”
và “Exploration”.
Điểm khác biệt quan trọng nhất giữa Scan và Exploration là việc Exploration
cho phép người dùng tùy chỉnh các output được hiện ra trong cửa sổ
Analysis, trong khi Scan chỉ thực việc công việc tìm kiếm các tín hiệu
buy/sell/short/cover và hiển thị chúng bằng các cột được định dạng từ trước.
Giả sử tôi mô phỏng 1 trading strategy dựa vào tin hiệu của MACD và Signal
Line như đoạn code bên dưới:
1

Buy = Cross(MACD(), Signal());

2

Sell = Cross(Signal(), MACD());

sau khi paste code vào formula rồi send to automatic analysis, tôi click scan
và được kết quả như hình bên dưới:


Về cơ bản, chức năng của Scan chỉ có vậy. Amibroker sẽ quét tìm trong
database lần lượt từng ngày các mã cổ phiếu thỏa mãn trading rule (buy/sell)
mà người dùng input vào, mỗi khi các tín hiệu thỏa mãn, Amibroker sẽ trả về
1 row các giá trị bao gồm Symbol, Trade, Date và Close như hình phía bên
trên.
Tiếp theo là chức năng exploration. Chức năng này mạnh hơn scan rất nhiều
bởi người dùng có thể tự định nghĩa các giá trị trả về cho column, không còn
giới hạn bởi 4 cột như scan.
Giả sử tôi muốn quét toàn bộ database của HOSE và HNX, sau đó trả về tên
mã cổ phiếu (Symbol), Ngày (Date), Giá đóng cửa (Close) và khối lượng
(Volume), tôi sẽ viết đoạn code như sau:
1

Filter = 1;

2

AddColumn(DateTime(), "Date", formatDateTime);

3

AddColumn(Close, "Close", 1.2);

4

AddColumn(Volume, "Volume", 1);


Đầu tiên là dòng Filter = 1. Exploration trong Amibroker yêu cầu người dùng
sử dụng hàm Filter khi sử dụng chức năng exploration, nếu trong code không
có hàm Filter, exploration sẽ không chạy. Filter = 1 được dùng để quét toàn
bộ các mã có trong cửa sổ apply to trong automatic analysis. Giả sử tôi để
apply to: All quotes, amibroker sẽ quét toàn bộ các mã có trong database.
Nếu chuyển thành apply to: watchlist0, amibroker sẽ quét toàn bộ các mã có
trong watchlist0. Ngoài ra trong exploration, người dùng có thể chọn range
tùy ý trên thanh công cụ, có thể là 1 recent-bar hoặc 1 khoảng nào đó (from
… to …). Hàm AddColumn được dùng để tạo các cột trong output của
Automatic Analysis, có thể check help index để xem chi tiết các parameters
cần thiết để pass vào function. Lưu ý là khi dùng hàm exploration, mặc định
sẽ có 2 cột là Ticker và Date/Time, người dùng không nhất thiết phải thêm
vào.

Xong phần cơ bản, giờ tôi sẽ đào sâu thêm 1 chút về hàm Filter. Ở mặt code,
giá trị để truyền vào hàm Filter sẽ có dạng boolean. Ở ví dụ trên, Filter = 1
tương đương Filter = True. Giờ giả sử tôi muốn lọc ra các cổ phiếu có khối
lượng giao dịch lớn hơn 10000 trong phiên gần nhất, tôi sẽ đặt Filter =
Volume > 10000, Hàm Filter sẽ trả về các ticker trong danh sách apply to
thỏa mãn điều kiện trên, sau đó các hàm phía dưới Filter sẽ thực hiện dựa
trên list trả về bởi hàm filter. Giả sử tôi có mã KDC, VGC và AAM trong
watchlist. Hàm Filter phía trên sẽ lọc từ watchlist ra 2 mã thỏa mãn là KDC và


VGC, sau đó các hàm Addcolumn phía bên dưới sẽ thực hiện nhiệm vụ dựa
trên 2 mã này, mã AAM bị loại bỏ. Thử đoạn code bên dưới với apply to: All
symbols và range : 1 recent-bar
1

Filter = Volume > 10000;

2

AddColumn(DateTime(), "Date", formatDateTime);

3

AddColumn(Close, "Close", 1.2);

4

AddColumn(Volume, "Volume", 1);

Amibroker cũng hỗ trợ thêm màu sắc vào trong các cột cũng như thêm các
cột có giá trị String (không phải số hay ngày tháng). Đoạn code bên dưới sẽ
minh họa ý tương này,

1

Filter = Volume > 10000;

2
3

CloseCond1 = Close > Ref(Close, -1);


4
5

CloseStatus1 = WriteIf(CloseCond1, "Close Bullish", "Close Bearish");
CloseColor1 = IIf(CloseCond1, colorGreen, colorRed);

6

AddColumn(Close, "Close", 1.2,colorWhite,CloseColor1);

7

AddTextColumn(CloseStatus1, "Close Status", 1, colorWhite, CloseColor1);

8
9

VolumeCond1 = Volume > Ref(Volume, -1);

10

VolumeStatus1 = WriteIf(VolumeCond1, "Volume Bullish", "Volume Bearish");

11

VolumeColor1 = IIf(VolumeCond1, colorGreen, colorRed);

12
13

AddColumn(Volume, "Volume", 1, colorWhite, VolumeColor1);
AddTextColumn(VolumeStatus1, "Close Status", 1, colorWhite, VolumeColor1);

Đoạn code này sẽ in ra các cột màu đỏ nếu Giá đóng cửa và khối lượng thấp
hơn ngày hôm trước, màu xanh nếu ngược lại. Ngoài ra còn in thêm 2 cột có
giá trị String tương ứng với Close và Volume.

Về mặt cơ bản, thế là hết cho scan và exploration. Giờ trader có thể tự thiết
kế bộ lọc của riêng mình với các indicator cũng như các hàm khác nhau trong


amibroker. Giả sử muốn lọc RSI > 70 và RSI < 30 chỉ cần type Filter = RSI >
70 or RSI < 30; hay muốn in ra các column thể hiện giá trị MA30 thì chỉ cần
AddColumn(MA(30), “MA30”, 1.2); là xong. Ý tưởng thiết kế nội dung là của
các bạn.
Phần sau tôi sẽ nói về Backtesting interface trong amibroker, một trong
những công cụ hay ho nhất của phần mềm này.

LOAD DỮ LIỆU CỔ PHIẾU TỪ
DATABASE AMIBROKER ĐẾN R
ENVIRONMENT (1)

Việt Nam ai ai cũng dùng metastock hoặc amibroker, thế nên dữ liệu cổ
phiếu cung cấp cho 2 phần mềm này rất nhiều. Vấn đề ở chỗ nhiều lúc
amibroker là không đủ để viết trading algorithm, hay làm data analysis, hay
đơn giản chỉ là đo độ nhạy của mã này với mã kia, với volume của chính nó.
Retail trader thì đương nhiên không có tool để access vào database như các
institutional trader, thế nên người ta lại nghĩ cách xuất ngược từ Amibroker
Database ra file CSV hoặc cơ sở dữ liệu cá nhân nào đó rồi load vào môi
trường của các ngôn ngữ khác như Python R hay Matlab. Ở Mỹ hay Eu hay
Singapore khác 1 chỗ là người ta có thể access data qua các API của Yahoo
hay Quandl, sau đó có ai đó viết sẵn function chỉ việc nhập ticker, start date,
end date là xong. Việt Nam thì tự viết tự quẩy, nhưng API thì chắc là khó
kiếm, thấy phổ biến nhất vẫn là dùng webscrapping trong VBA rồi load
fundamental data vào.
Amibroker cung cấp bộ code sau để xuất toàn dữ liệu OHLCV ra file .csv
hay .txt như sau:
?

1

// create folder for exporting purposes

2

fmkdir( "C:\\DataExport\\" );

3
4
5
6
7

// open file for writing
// file name depends on currently processed ticker
fh = fopen( "c:\\DataExport\\" + Name() + ".txt", "w" );

// proceed if file handle is correct


8

if ( fh )

9

{
dt = DateTime();

10
11

// write header line

12

fputs( "Ticker,Date/Time,Open,High,Low,Close,Volume\n", fh );

13
14

// iterate through all the bars

15
16

for ( i = 0; i < BarCount; i++ )

17

{

18

// write ticker name

19

fputs( Name() + "," , fh );

20
21

// write date/time information

22

fputs( DateTimeToStr( dt[ i ] ) + ",", fh );

23
//write quotations and go to the next line

24

qs = StrFormat( "%g,%g,%g,%g,%g\n", O[ i ], H[ i ], L[ i ], C[ i ], V[ i ] );

25

fputs( qs, fh );

26
27

}

28

// close file handle

29
30

fclose( fh );
}

31
32

// line required by SCAN option

33

Buy = 0;

34
35


36

Load đoạn code trên vào automatic analysis rồi explore cho watchlist cần
xuất data. Giả sử tôi có watchlist0 bao gồm : KDC, VNM, VCB và VIC, sau khi
export sẽ đc 4 file như sau:

Sau đó vào Rstudio chỉnh set working directory as vào thư mục
c:\\DataExport, cái này có thể thay đổi được trong phần code của Amibroker.
Sau đó dùng đoạn code sau để load toàn bộ data vào môi trường R, tên
variable trùng với tên của file xuất từ amibroker loại bỏ hậu tố “.csv”
1

#solution 1

2

mf1 <- list.files(pattern = "*.txt")

3

# create vector of file name from WD

4

n1 <- gsub("*.txt","", mf1)


5

# remove suffix ".txt"

6
7

for (i in n1){

8

tempname <- paste(i)

9

#Create variable to store name

10

assign(tempname, read.csv(paste(tempname,".txt", sep=""), header = TRUE))

11

#pass data from .txt file to variable created

12

}

Kết quả là trong environment giờ có 4 variables tương ứng với 4 file .txt xuất
từ amibroker:

Giờ đến phần clean data, giờ tôi muốn số liệu là 500 ngày trading tính ngược
từ thời điểm hôm nay. Vậy tức là phải subset lại toàn bộ chuỗi data. Đoạn
code sau dùng for loop để thực hiện việc này
1

for (i in n1){

2

a <- get(i)

3

#get data from strings in vector n1

4
5
6
7

tempname <- paste(i)
#create variable to store name
end <- nrow(a)
start <- nrow(a) - 500
a <- a[start:end,]


8
9

assign(tempname,a)
}

10

Đến bước này thì cơ bản đã có 4 variables tương ứng với 4 file dữ liệu load từ
amibroker vào. Giờ thử làm 1 số analysis cơ bản cho data đã được lọc. Đầu
tiên xem xét cấu trúc của dữ liệu:
1
2

> head(KDC,3)
Ticker Date.Time

3
4
5
6
7
8

Open High

Low Close

Volume

2807

KDC 3/21/2017 39.00 39.6 39.0

39.0

371290

2806

KDC 3/20/2017 39.00 39.4 38.7

38.7

326090

2805

KDC 3/17/2017 37.45 38.9 37.4

37.5 4787880

> tail(KDC,3)
Ticker Date.Time

Open

High

Low

Close Volume

2309

KDC 3/25/2015 24.490 24.648 24.383 24.383 364990

9

2308

KDC 3/24/2015 24.806 24.806 24.224 24.490 554660

10

2307

KDC 3/23/2015 25.338 25.338 24.595 24.648 721450

11

> dim(KDC)

12

[1] 501

13

> str(KDC)

14
15
16

7

'data.frame':
$ Ticker

501 obs. of

7 variables:

: Factor w/ 1 level "KDC": 1 1 1 1 1 1 1 1 1 1 ...

$ Date.Time: Factor w/ 2807 levels "1/10/2006","1/10/2007",..: 1284 1275 1241 1232 1
$ Open

: num

39 39 37.5 37.2 37.2 ...

$ High

: num

39.6 39.4 38.9 37.4 37.3 ...

18

$ Low

: num

39 38.7 37.4 37.1 37.1 ...

19

$ Close

: num

39 38.7 37.5 37.4 37.1 ...

20

$ Volume

: num

371290 326090 4787880 106550 446050 ...

17

21

Sau đó dựa vào closing price tính toán daily return , log return, mean,
median, test các test liên quan đến time-series data. Đầu tiên phải đưa tất cả
closing price vào 1 dataframe.


1

> # 1.Clean Data

2

> df <- data.frame(date =KDC$Date.Time) > #Create empty dataframe with Date from any

3

> head(df)

4
5
6

date
1 3/21/2017
2 3/20/2017
3 3/17/2017

7

4 3/16/2017

8

5 3/15/2017

9

6 3/14/2017

10

> #create empty buffer

11

> for ( i in n1){

12

+ temp <- get(i)

13
14
15

+ AdjClose <- temp$Close
+ #extract Close Price
+ names(AdjClose) <- paste(i)
+ df <- cbind(df,AdjClose)

16

+ }

17

> head(df,3)

18

date AdjClose AdjClose AdjClose AdjClose

19

1 3/21/2017 39.0 38.00 41.45 135.6

20

2 3/20/2017 38.7 37.55 43.30 133.9

21

3 3/17/2017 37.5 37.00 43.80 134.0

22
23
24

> colnames(df) <- c("Date", n1) > # Name the columns
> df <- df[nrow(df):1,] > # Reverse the dataframe
> head(df,10)
Date KDC VCB VIC VNM

25

501 3/23/2015 24.648 25.012 28.236 67.841

26

500 3/24/2015 24.490 25.083 28.236 67.841

27

499 3/25/2015 24.383 25.154 28.177 67.841

28

498 3/26/2015 24.118 24.870 27.768 67.841
497 3/27/2015 23.853 25.083 27.535 66.574


29
30
31
32

496 3/30/2015 23.588 24.942 27.243 66.574

33

495 3/31/2015 23.853 24.942 27.476 67.206

34

494 4/1/2015 23.323 24.870 26.892 66.574

35
36
37
38

493 4/2/2015 23.588 25.368 27.067 67.206
492 4/3/2015 23.534 25.368 26.950 66.574
> str(df)
'data.frame': 501 obs. of 5 variables:

$ Date: Factor w/ 2807 levels "1/10/2006","1/10/2007",..: 1298 1306 1314 1323 1331 13

39

$ KDC : num 24.6 24.5 24.4 24.1 23.9 ...

40

$ VCB : num 25 25.1 25.2 24.9 25.1 ...

41

$ VIC : num 28.2 28.2 28.2 27.8 27.5 ...

42

$ VNM : num 67.8 67.8 67.8 67.8 66.6 ...

43

> # Re-order data by Date in first column

44
45
46
47

> Date <- as.Date(df[,1], format = "%m/%d/%Y") > df <- cbind(Date, df[,-1]) > df <- d
Date KDC VCB VIC VNM
501 2015-03-23 24.648 25.012 28.236 67.841
500 2015-03-24 24.490 25.083 28.236 67.841
499 2015-03-25 24.383 25.154 28.177 67.841

48

498 2015-03-26 24.118 24.870 27.768 67.841

49

497 2015-03-27 23.853 25.083 27.535 66.574

50

496 2015-03-30 23.588 24.942 27.243 66.574

51
52
53

Phần dưới sẽ minh họa thống kê mô tả của bộ data
1

# Simple Plot

2

par(mfrow = c(2,2), mar = c(2,4,4,2))


3
4

for (i in 2:ncol(df)){
plot(x = df$Date, y = df[,i],

5

col = "brown3", type = 'l',

6

ylab = "Price",

7

xlab = "date",

8
9

main = paste("Price of", colnames(df)[i]))
}

10

# ggplot2

11

gg1 <- NULL

12

for (i in 2:ncol(df)){

13

temp <- data.frame(Date = df$Date,

14

price = df[,i],
ticker = colnames(df[i]))

15

gg1 <- rbind(gg1, temp)

16
17
18
19

}
head(gg1)
ggplot1 <- ggplot(data = gg1, aes(x = Date, y = price, col = ticker))

20

ggplot1 <- ggplot1 + geom_line(size = 1) + ggtitle("Price Chart")

21

ggplot1

22


1

# Extract only relevent columns

2

nc <- ncol(df)

3

ret <- df[,-1]

4
5
6

# Calculate Daily Return
head(ret)


7

# Calculate Log Return

8

log_ret <- log(ret)

9

log_ret <- apply(log_ret, MARGIN = 2,

10
11
12
13
14

"diff")

head(log_ret,3)

# Calculate Arithmetic Return
ar_ret <- apply(ret, MARGIN = 2, "diff")
ar_ret <- ar_ret/ret[1:nrow(ret)-1,]
head(ar_ret,3)

15
16

#summary of return

17

summary(log_ret)

18

summary(ar_ret)

19
20

par(mfrow = c(2,2), mar = c(2,4,4,2))

21

# Plot return graph

22

for ( i in 1:ncol(log_ret)){
temp <- colnames(log_ret)[i]

23

plot(log_ret[,i], col = "brown1",

24

main = paste("log daily return of", temp),

25

xlab = "date",

26

ylab = "% daily return")

27

}

28
29

# Plot histogram of log return

30

for ( i in 1:ncol(log_ret)){
temp <- colnames(log_ret)[i]

31

hist(log_ret[,i], col = "brown2",

32

main = paste("histogram of", temp),

33
34

breaks = 10)
}


35
36
37
38
39
40
41

for (i in 1:ncol(log_ret)){
acf(log_ret[,i])
}


Vậy cuối cùng ý tưởng ở đây là gì?
Đó là việc tự động hóa toàn bộ quá trình analysis diễn ra chỉ bằng câu lệnh
xuất data của amibroker sau đó mô hình tự update cho những ngày hôm sau.
Bình thường nếu dùng các công cụ thốn g kê như eviews hay stata, rất khó
để có loop, while hay if else. Dù sao thì code cũng tiết kiệm rất nhiều thời
gian.


Hơn nữa, trong Amibroker có chức năng nhóm các cổ phiếu thuộc cùng nhóm
ngành với nhau, vậy mỗi lần xuất data, đọc một working directory mới, ta có
cái nhìn update liên tục về diễn biến cũng như thống kê của từng sector,
từng industry riêng lẻ.
Còn rất nhiều thứ nữa có thể dùng để analyze, giả sử update thông tin về
correlation của các mã, beta update daily hay đơn giản là update thông số
value-at-risk của portfolio. Có thể sử dụng các package khác để đo độ nhạy
cảm của danh mục đầu tư với Forex, thị trường chứng khoán Mỹ, EU, mà có
thông tin trên yahoo finance hoặc quandl. Technical analysis indicators cũng
có thể tìm được trên các package thông dụng như TTR, quantmod hay
tseries. Nếu cần rebalance và optimize lại portfolio, có thể sử dụng package
fPortfolio của Rmetrics. Vấn đề đau đầu nữa là bạn có đủ data không? retail
traders có data để feed vào model không?
Ở bài viết sau tôi sẽ viết một bộ lọc để lọc cổ phiếu cho thị trường Việt Nam,
sau đó chạy mô hình Fama-French với thuật toán củ chính tác giả
(http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/data_library.html).
Tuy nhiên R chỉ tốt về mặt thống kê, có nghĩa là sử dụng R cho thống kê phân
tích data thì hoàn toàn ổn, còn để backtesting hay develop trading model thì
không hợp lý lắm, có vô số lý do tại sao và bạn có thể google. Lý do quan
trọng nhất là R rất chậm, không phù hợp cho các project lớn cần tính linh
hoạt.
Nếu institutional traders có database source thì việc develop system như
trên sẽ hoàn toàn trở nên vô nghĩa bởi R cũng hỗ trợ các nền tảng csdl như
mysql, sql…..



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay

×