由於預估量對當沖操作者很重要,一直有使用者來信詢問我們系統內建預估量的計算方法,也有不少熱心的使用者建議了一些演算方式。我們目前系統內建的演算法是依過往每分鐘成交量分佈比重,然後從當天的累計量去估算預估量,這樣的作法大家意見不大,但對於要拿多少天的歷史資料去估算成交量分佈情況,大家的意見差很多,我們公司的高手高高手,索性公開預估量的計算腳本,並且把成交量分佈比重究竟要拿多少天的歷史資料去估算,設成參數讓使用者自行來設計,這樣一來,大家就可以很容易的透過調整參數的方式,找到自己認為最貼近事實的估計量
這個估計量的腳本如果作成指標,其腳本如下
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;
至於預估量的成交量分配要用過往幾天的值來估算,我個人偏向於不要太長,因為太長要計算的時間很久,而且跟目前的交易實況可能會有落差。
以上是預估量的計算腳本大公開
有不同想法的朋友也可以再提出來
大家的目標都是想要把預估量計算的愈來愈貼近實際量
