依成交量分佈情況而設計的預估量演算法

By | 2019-07-19

由於預估量對當沖操作者很重要,一直有使用者來信詢問我們系統內建預估量的計算方法,也有不少熱心的使用者建議了一些演算方式。我們目前系統內建的演算法是依過往每分鐘成交量分佈比重,然後從當天的累計量去估算預估量,這樣的作法大家意見不大,但對於要拿多少天的歷史資料去估算成交量分佈情況,大家的意見差很多,我們公司的高手高高手,索性公開預估量的計算腳本,並且把成交量分佈比重究竟要拿多少天的歷史資料去估算,設成參數讓使用者自行來設計,這樣一來,大家就可以很容易的透過調整參數的方式,找到自己認為最貼近事實的估計量

這個估計量的腳本如果作成指標,其腳本如下

1//
2// 參數: 統計天期(N)
3// 繪製: 當日估計成交量
4//
5// 支援任何頻率(分鐘/日)
6//
7// 計算方式: 依照過去N日, 每日1分鐘累計成交均量(統計天期平均), 算出每分鐘累計成交量的分佈比例, 
8// 然後依照目前的累計日成交量以及分佈比例, 推算當日收盤估計成交量
9//
10
11input: length(5, "統計天數");
12
13variable: BARPERDAY(270); // 1分鐘bar每一天270筆
14
15array: arr_minvolume[](0); // (過去N日)每日每分鐘累計: 共length * 270筆
16array: arr_minvolume_percent[270](0); // (平均)每分鐘累計成交量比例: 共270筆
17array: arr_avg_minvolume[270](0); // (平均)每分鐘累計成交量: 共270筆
18
19variable: _i(0), _j(0), _k(0);
20variable: _totaldays(0);
21variable: _lastdate(0);
22
23Array_SetMaxIndex(arr_minvolume, length * 270);
24
25{
26print(text(
27"currentbar=", numtostr(currentbar, 0), 
28",date=", numtostr(date, 0), 
29",time=", numtostr(time, 0),
30",lastdate=", numtostr(_lastdate, 0),
31",totaldays=", numtostr(_totaldays, 0)
32));
33}
34
35if _lastdate = 0 then begin
36// 跳過第一個不滿一天的資料
37if barfreq = "Min" and time = 090000 then
38_lastdate = date
39else begin
40// 日線的話則從20190101才開始算
41if date >= 20190101 then
42_lastdate = date;
43end; 
44end;
45
46if _lastdate <> 0 and date <> _lastdate then begin
47_lastdate = date;
48_totaldays = _totaldays + 1;
49if _totaldays >= length then begin
50// 計算過去N天的成交量分佈
51//
52// 因為我可能跑在不同頻率上, 所以要先算出過去N日'1分鐘'資料的起點跟終點
53//
54variable: _start(0), _end(0), _startdate(0), _accvolume(0);
55
56_end = 1;
57while getfield("time", "1")[_end] <> 132900 begin
58_end = _end + 1;
59end;
60
61_start = _end + BARPERDAY * length - 1;
62
63// _start = 統計日期第一日第一筆1分鐘資料的位置
64// _end = 統計日期最後一日最後一筆1分鐘資料的位置
65//
66
67// arr_minvolume[]: 儲存過去N天, 每一分鐘的日累積成交量
68// arr_minvolume[1] = 09:00, 
69// arr_minvolume[2] = 09:01
70// arr_minvolume[271] = 第二天09:00
71// ..
72_startdate = getfield("date", "1")[_start];
73_accvolume = 0;
74for _i = _start downto _end begin
75if _startdate <> getfield("date", "1")[_i] then begin
76// 換日
77_accvolume = 0;
78_startdate = getfield("date", "1")[_i];
79end;
80_accvolume += getfield("volume", "1")[_i];
81arr_minvolume[_start - _i + 1] = _accvolume; // 當日累積volume
82end;
83
84// arr_avg_minvolume[]: 每一分鐘的日平均累積成交量
85//
86for _j = 1 to BARPERDAY begin
87arr_avg_minvolume[_j] = 0;
88for _i = 1 to length begin
89arr_avg_minvolume[_j] += arr_minvolume[_j + (_i - 1) * BARPERDAY];
90end; 
91end;
92for _j = 1 to BARPERDAY begin
93arr_avg_minvolume[_j] = arr_avg_minvolume[_j] / length;
94end;
95
96// arr_minvolume_percent[]: 每一分鐘的日平均累積成交量%
97//
98for _j = 1 to BARPERDAY begin
99arr_minvolume_percent[_j] = arr_avg_minvolume[_j] / arr_avg_minvolume[BARPERDAY];
100end;
101
102{
103print(text(
104"main-date=", numtostr(date, 0), ",",
105"main-time=", numtostr(time, 0), ",",
106"start=", numtostr(_start, 0), ",",
107"end=", numtostr(_end, 0), ",",
108"startdate=", numtostr(getfield("date", "1")[_start], 0), ",", numtostr(getfield("time", "1")[_start], 0), ",",
109"enddate=", numtostr(getfield("date", "1")[_end], 0), ",", numtostr(getfield("time", "1")[_end], 0), ","
110));
111
112for _i = 1 to 270 begin
113print(text(
114numtostr(_i, 0), "=", 
115numtostr(arr_minvolume_percent[_i] * 100, 2))); 
116end; 
117}
118end;
119end;
120
121if _totaldays >= length then begin
122// 如果已經有分佈資料了, 則計算估計成交量
123//
124variable: _estvolume(0);
125variable: _timeindex(0);
126variable: _time(0), _v(0);
127
128// 算出目前時間應該是1~270的哪一筆
129// 分鐘線的話就用bar的時間
130// 日線的話, 如果是歷史日線, 就用收盤時間估算, 如果是最後一天(盤中日線), 用目前時間估算
131//
132if barfreq = "Min" then
133_time = time
134else begin
135if date < currentdate then
136_time = 132900
137else 
138_time = currenttime;
139end;
140_timeindex = floor(timediff(_time, 090000, "M")) + 1;
141_timeindex = minlist(_timeindex, 270);
142_timeindex = maxlist(1, _timeindex);
143
144// 預估量 = 累計到目前的日成交量 / 這個時間點之前所佔的日成交量%
145//
146_v = GetField("volume", "D");
147if arr_minvolume_percent[_timeindex] > 0 then
148_estvolume = _v / arr_minvolume_percent[_timeindex]
149else
150_estvolume = 0;
151
152plot1(_estvolume, "預估量");
153end;

我也試著把這個預估量的腳本寫成函數

1input: length(numericsimple);
2
3variable: BARPERDAY(270); // 1分鐘bar每一天270筆
4
5array: arr_minvolume[](0); // (過去N日)每日每分鐘累計: 共length * 270筆
6array: arr_minvolume_percent[270](0); // (平均)每分鐘累計成交量比例: 共270筆
7array: arr_avg_minvolume[270](0); // (平均)每分鐘累計成交量: 共270筆
8
9variable: _i(0), _j(0), _k(0);
10variable: _totaldays(0);
11variable: _lastdate(0);
12
13Array_SetMaxIndex(arr_minvolume, length * 270);
14
15{
16print(text(
17"currentbar=", numtostr(currentbar, 0), 
18",date=", numtostr(date, 0), 
19",time=", numtostr(time, 0),
20",lastdate=", numtostr(_lastdate, 0),
21",totaldays=", numtostr(_totaldays, 0)
22));
23}
24
25if _lastdate = 0 then begin
26// 跳過第一個不滿一天的資料
27if barfreq = "Min" and time = 090000 then
28_lastdate = date
29else begin
30// 日線的話則從20190101才開始算
31if date >= 20190101 then
32_lastdate = date;
33end; 
34end;
35
36if _lastdate <> 0 and date <> _lastdate then begin
37_lastdate = date;
38_totaldays = _totaldays + 1;
39if _totaldays >= length then begin
40// 計算過去N天的成交量分佈
41//
42// 因為我可能跑在不同頻率上, 所以要先算出過去N日'1分鐘'資料的起點跟終點
43//
44variable: _start(0), _end(0), _startdate(0), _accvolume(0);
45
46_end = 1;
47while getfield("time", "1")[_end] <> 132900 begin
48_end = _end + 1;
49end;
50
51_start = _end + BARPERDAY * length - 1;
52
53// _start = 統計日期第一日第一筆1分鐘資料的位置
54// _end = 統計日期最後一日最後一筆1分鐘資料的位置
55//
56
57// arr_minvolume[]: 儲存過去N天, 每一分鐘的日累積成交量
58// arr_minvolume[1] = 09:00, 
59// arr_minvolume[2] = 09:01
60// arr_minvolume[271] = 第二天09:00
61// ..
62_startdate = getfield("date", "1")[_start];
63_accvolume = 0;
64for _i = _start downto _end begin
65if _startdate <> getfield("date", "1")[_i] then begin
66// 換日
67_accvolume = 0;
68_startdate = getfield("date", "1")[_i];
69end;
70_accvolume += getfield("volume", "1")[_i];
71arr_minvolume[_start - _i + 1] = _accvolume; // 當日累積volume
72end;
73
74// arr_avg_minvolume[]: 每一分鐘的日平均累積成交量
75//
76for _j = 1 to BARPERDAY begin
77arr_avg_minvolume[_j] = 0;
78for _i = 1 to length begin
79arr_avg_minvolume[_j] += arr_minvolume[_j + (_i - 1) * BARPERDAY];
80end; 
81end;
82for _j = 1 to BARPERDAY begin
83arr_avg_minvolume[_j] = arr_avg_minvolume[_j] / length;
84end;
85
86// arr_minvolume_percent[]: 每一分鐘的日平均累積成交量%
87//
88for _j = 1 to BARPERDAY begin
89arr_minvolume_percent[_j] = arr_avg_minvolume[_j] / arr_avg_minvolume[BARPERDAY];
90end;
91
92{
93print(text(
94"main-date=", numtostr(date, 0), ",",
95"main-time=", numtostr(time, 0), ",",
96"start=", numtostr(_start, 0), ",",
97"end=", numtostr(_end, 0), ",",
98"startdate=", numtostr(getfield("date", "1")[_start], 0), ",", numtostr(getfield("time", "1")[_start], 0), ",",
99"enddate=", numtostr(getfield("date", "1")[_end], 0), ",", numtostr(getfield("time", "1")[_end], 0), ","
100));
101
102for _i = 1 to 270 begin
103print(text(
104numtostr(_i, 0), "=", 
105numtostr(arr_minvolume_percent[_i] * 100, 2))); 
106end; 
107}
108end;
109end;
110
111if _totaldays >= length then begin
112// 如果已經有分佈資料了, 則計算估計成交量
113//
114variable: _estvolume(0);
115variable: _timeindex(0);
116variable: _time(0), _v(0);
117
118// 算出目前時間應該是1~270的哪一筆
119// 分鐘線的話就用bar的時間
120// 日線的話, 如果是歷史日線, 就用收盤時間估算, 如果是最後一天(盤中日線), 用目前時間估算
121//
122if barfreq = "Min" then
123_time = time
124else begin
125if date < currentdate then
126_time = 132900
127else 
128_time = currenttime;
129end;
130_timeindex = floor(timediff(_time, 090000, "M")) + 1;
131_timeindex = minlist(_timeindex, 270);
132_timeindex = maxlist(1, _timeindex);
133
134// 預估量 = 累計到目前的日成交量 / 這個時間點之前所佔的日成交量%
135//
136_v = GetField("volume", "D");
137if arr_minvolume_percent[_timeindex] > 0 then
138_estvolume = _v / arr_minvolume_percent[_timeindex]
139else
140_estvolume = 0;
141destvolume=_estvolume;
142end;

 

利用這個Destvolume的函數,我們就可以寫出預估量比五日均量增加N%的警示腳本

 

1input:day(10,"預估量估算期間");
2input:period(20,"均量計算期間");
3input:ratio(80," 暴量比例");
4if destvolume(day) crosses over average(volume,period)*(1+ratio/100)
5and close>close[1]*1.01
6then ret=1;

 

 

至於預估量的成交量分配要用過往幾天的值來估算,我個人偏向於不要太長,因為太長要計算的時間很久,而且跟目前的交易實況可能會有落差。

以上是預估量的計算腳本大公開

有不同想法的朋友也可以再提出來

大家的目標都是想要把預估量計算的愈來愈貼近實際量