Skip to content

Commit

Permalink
Merge pull request #212 from miles170/fix-tpex
Browse files Browse the repository at this point in the history
修正證券櫃檯買賣中心抓取資訊失敗
  • Loading branch information
miles170 authored Oct 28, 2024
2 parents 44cced7 + 8770e70 commit 0f97794
Show file tree
Hide file tree
Showing 5 changed files with 476 additions and 213 deletions.
2 changes: 1 addition & 1 deletion test/integration/quote_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestQuote_DownloadTpex(t *testing.T) {
client := twstock.NewClient()
_, err := client.Quote.DownloadTpex("3374", 2022, 12)
if err != nil {
t.Fatalf("DownloadTwse returned error: %v", err)
t.Fatalf("DownloadTpex returned error: %v", err)
}
_, err = client.Quote.DownloadTpex("2330", 2022, 12)
if err != twstock.ErrNoData {
Expand Down
26 changes: 17 additions & 9 deletions twstock/marketdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const (
twseMarketDataPath = "/exchangeReport/FMTQIK"

// 上櫃每日市場成交資訊
tpexMarketDataPath = "/web/stock/aftertrading/daily_trading_index/st41_result.php"
tpexMarketDataPath = "/www/zh-tw/afterTrading/tradingIndex"
)

type MarketData struct {
Expand Down Expand Up @@ -130,8 +130,8 @@ func (s *MarketDataService) DownloadTpex(year int, month time.Month) ([]MarketDa
}
url, _ := s.client.tpexBaseURL.Parse(tpexMarketDataPath)
opts := tpexOptions{
// 需要將西元年轉為民國年
Date: fmt.Sprintf("%d/%02d", date.Year-1911, date.Month),
Response: "json",
Date: fmt.Sprintf("%04d/%02d/%02d", date.Year, date.Month, date.Day),
}
url, _ = addOptions(url, opts)
req, _ := s.client.NewRequest("GET", url.String(), nil)
Expand All @@ -140,18 +140,26 @@ func (s *MarketDataService) DownloadTpex(year int, month time.Month) ([]MarketDa
if err != nil {
return nil, err
}
if resp.DataLength != len(resp.Data) {
return nil, fmt.Errorf("failed parsing market data length returned %d, want %d", resp.DataLength, len(resp.Data))
}
if resp.DataLength == 0 {
if len(resp.Tables) != 1 || resp.Tables[0].TotalCount == 0 {
return nil, ErrNoData
}
if resp.Tables[0].TotalCount != len(resp.Tables[0].Data) {
return nil, fmt.Errorf("failed parsing market data length returned %d, want %d", resp.Tables[0].TotalCount, len(resp.Tables[0].Data))
}
result := []MarketData{}
for _, data := range resp.Data {
marketData, err := s.parse(data)
for _, data := range resp.Tables[0].Data {
stringData := make([]string, len(data))
for i, v := range data {
stringData[i] = string(v)
}
marketData, err := s.parse(stringData)
if err != nil {
return nil, err
}
// 成交股數(仟股)
marketData.TradeVolume *= 1000
// 金額(仟元)
marketData.TradeValue = marketData.TradeValue.Mul(decimal.NewFromInt(1000))
result = append(result, marketData)
}
return result, nil
Expand Down
216 changes: 144 additions & 72 deletions twstock/marketdata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,50 +304,70 @@ func TestMarketDataService_DownloadTpex(t *testing.T) {
mux.HandleFunc(tpexMarketDataPath, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
fmt.Fprint(w, `{
"reportDate": "111/08",
"iTotalRecords": 5,
"aaData": [
[
"111/08/01",
"630,222,871",
"46,240,795,178",
"436,953",
"182.75",
"-0.83"
],
[
"111/08/02",
"694,614,949",
"51,249,692,749",
"484,905",
"179.30",
"-3.45"
],
[
"111/08/03",
"683,637,182",
"50,799,048,121",
"473,344",
"178.17",
"-1.13"
],
[
"111/08/04",
"677,879,834",
"51,578,056,349",
"458,468",
"178.18",
"0.01"
],
[
"111/08/05",
"651,963,371",
"57,144,930,041",
"435,858",
"182.37",
"4.19"
]
]
"tables": [
{
"title": "日成交量值指數",
"date": "20220801",
"data": [
[
"111/08/01",
"630,223",
"46,240,795",
"436,953",
182.75,
-0.83
],
[
"111/08/02",
"694,615",
"51,249,693",
"484,905",
179.30,
-3.45
],
[
"111/08/03",
"683,637",
"50,799,048",
"473,344",
178.17,
-1.13
],
[
"111/08/04",
"677,880",
"51,578,056",
"458,468",
178.18,
0.01
],
[
"111/08/05",
"651,963",
"57,144,930",
"435,858",
182.37,
4.19
]
],
"fields": [
"日期",
"成交股數(仟股)",
"金額(仟元)",
"筆數",
"櫃買指數",
"漲/跌"
],
"notes": [
"上表為於等價、零股、盤後定價等交易系統交易之上櫃股票成交資訊。",
"每日下午6:00另行產製於等價、零股、盤後定價、鉅額等交易系統交易之上櫃股票、權證、TDR、ETF、ETN、受益證券等上櫃有價證券之成交資訊,但不含轉(交)換公司債之成交統計報表,如<a href=\"daily-indices-rpk.html\">連結</a>"
],
"totalCount": 5,
"summary": []
}
],
"date": "20220801",
"stat": "ok"
}`)
})

Expand All @@ -358,40 +378,40 @@ func TestMarketDataService_DownloadTpex(t *testing.T) {
want := []MarketData{
{
Date: civil.Date{Year: 2022, Month: time.August, Day: 1},
TradeVolume: 630222871,
TradeValue: decimal.NewFromInt(46240795178),
TradeVolume: 630223000,
TradeValue: decimal.NewFromInt(46240795000),
Transaction: 436953,
Index: decimal.NewFromFloat(182.75),
Change: decimal.NewFromFloat(-0.83),
},
{
Date: civil.Date{Year: 2022, Month: time.August, Day: 2},
TradeVolume: 694614949,
TradeValue: decimal.NewFromInt(51249692749),
TradeVolume: 694615000,
TradeValue: decimal.NewFromInt(51249693000),
Transaction: 484905,
Index: decimal.NewFromFloat(179.30),
Change: decimal.NewFromFloat(-3.45),
},
{
Date: civil.Date{Year: 2022, Month: time.August, Day: 3},
TradeVolume: 683637182,
TradeValue: decimal.NewFromInt(50799048121),
TradeVolume: 683637000,
TradeValue: decimal.NewFromInt(50799048000),
Transaction: 473344,
Index: decimal.NewFromFloat(178.17),
Change: decimal.NewFromFloat(-1.13),
},
{
Date: civil.Date{Year: 2022, Month: time.August, Day: 4},
TradeVolume: 677879834,
TradeValue: decimal.NewFromInt(51578056349),
TradeVolume: 677880000,
TradeValue: decimal.NewFromInt(51578056000),
Transaction: 458468,
Index: decimal.NewFromFloat(178.18),
Change: decimal.NewFromFloat(0.01),
},
{
Date: civil.Date{Year: 2022, Month: time.August, Day: 5},
TradeVolume: 651963371,
TradeValue: decimal.NewFromInt(57144930041),
TradeVolume: 651963000,
TradeValue: decimal.NewFromInt(57144930000),
Transaction: 435858,
Index: decimal.NewFromFloat(182.37),
Change: decimal.NewFromFloat(4.19),
Expand Down Expand Up @@ -430,9 +450,36 @@ func TestMarketDataService_DownloadTpexErrNoData(t *testing.T) {
mux.HandleFunc(tpexMarketDataPath, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
fmt.Fprint(w, `{
"reportDate": "111/08",
"iTotalRecords": 0,
"aaData": []
"date": "20220801",
"stat": "ok",
"tables": []
}`)
})

_, err := client.MarketData.DownloadTpex(2022, 8)
if err == nil {
t.Error("MarketData.DownloadTpex returned nil; expected error")
}
if !errors.Is(err, ErrNoData) {
t.Errorf("MarketData.DownloadTpex returned %v, want %v", err, ErrNoData)
}
}

func TestMarketDataService_DownloadTpexErrNoData2(t *testing.T) {
client, mux, teardown := setup()
defer teardown()

mux.HandleFunc(tpexMarketDataPath, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
fmt.Fprint(w, `{
"date": "20220801",
"stat": "ok",
"tables": [
{
"data": [],
"totalCount": 0
}
]
}`)
})

Expand All @@ -452,9 +499,14 @@ func TestMarketDataService_DownloadTpexBadDataLength(t *testing.T) {
mux.HandleFunc(tpexMarketDataPath, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
fmt.Fprint(w, `{
"reportDate": "111/08",
"iTotalRecords": 1,
"aaData": []
"tables": [
{
"data": [],
"totalCount": 1
}
],
"date": "20220801",
"stat": "ok"
}`)
})

Expand All @@ -471,18 +523,38 @@ func TestMarketDataService_DownloadTpexBadData(t *testing.T) {
mux.HandleFunc(tpexMarketDataPath, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
fmt.Fprint(w, `{
"reportDate": "111/08",
"iTotalRecords": 1,
"aaData": [
[
"111/30/01",
"630,222,871",
"46,240,795,178",
"436,953",
"182.75",
"-0.83"
]
]
"tables": [
{
"title": "日成交量值指數",
"date": "20220801",
"data": [
[
"111/08/01",
"BADDATA",
"46,240,795",
"436,953",
182.75,
-0.83
]
],
"fields": [
"日期",
"成交股數(仟股)",
"金額(仟元)",
"筆數",
"櫃買指數",
"漲/跌"
],
"notes": [
"上表為於等價、零股、盤後定價等交易系統交易之上櫃股票成交資訊。",
"每日下午6:00另行產製於等價、零股、盤後定價、鉅額等交易系統交易之上櫃股票、權證、TDR、ETF、ETN、受益證券等上櫃有價證券之成交資訊,但不含轉(交)換公司債之成交統計報表,如<a href=\"daily-indices-rpk.html\">連結</a>"
],
"totalCount": 1,
"summary": []
}
],
"date": "20220801",
"stat": "ok"
}`)
})

Expand Down
Loading

0 comments on commit 0f97794

Please sign in to comment.