From 9ea4b61ee3461be6d15c63bd40d5158be652ee69 Mon Sep 17 00:00:00 2001 From: yangfan <784310601@qq.com> Date: Thu, 7 May 2026 17:26:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9ET-1=E6=97=A5=E5=BC=80?= =?UTF-8?q?=E7=9B=98=E6=B6=A8=E8=B7=8C=E5=B9=85=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/download-second-board-profit-csv.md | 3 +++ internal/api/limit_second_profit_csv_handler.go | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/docs/download-second-board-profit-csv.md b/docs/download-second-board-profit-csv.md index 95f72ae..d51168c 100644 --- a/docs/download-second-board-profit-csv.md +++ b/docs/download-second-board-profit-csv.md @@ -95,6 +95,7 @@ GET /api/v1/download/limit-board/second-board-profit-csv?tradeStartDate=2026-04- | `name` | `string` | `股票简称` | 股票简称 | | `market` | `string` | `市场` | 市场信息 | | `industry` | `string` | `行业` | 所属行业 | +| `previous_open_pct_chg` | `number \| null` | `T-1日开盘涨跌幅%` | T-1 日开盘价相对 T-2 收盘价的涨跌幅百分比 | | `open_pct_chg` | `number \| null` | `T日开盘涨跌幅%` | T 日开盘价相对 T-1 收盘价的涨跌幅百分比 | | `next_open_pct_chg` | `number \| null` | `T+1日开盘涨跌幅%` | T+1 日开盘价相对 T 日收盘价的涨跌幅百分比 | | `next_open_profitable` | `string` | `T+1开盘是否盈利` | T+1 开盘收益大于 0 时为 `是`,否则为 `否`;无次日数据时为 `无次日数据` | @@ -133,6 +134,7 @@ GET /api/v1/download/limit-board/second-board-profit-csv?tradeStartDate=2026-04- "name": "示例股份", "market": "主板", "industry": "软件开发", + "previous_open_pct_chg": -1.25, "open_pct_chg": 1.36, "next_open_pct_chg": 2.38, "next_open_profitable": "是", @@ -166,6 +168,7 @@ CSV 字段顺序: | `股票简称` | 股票简称 | | `市场` | 市场信息 | | `行业` | 所属行业 | +| `T-1日开盘涨跌幅%` | T-1 日开盘价相对 T-2 收盘价的涨跌幅百分比 | | `T日开盘涨跌幅%` | T 日开盘价相对 T-1 收盘价的涨跌幅百分比 | | `T+1日开盘涨跌幅%` | T+1 日开盘价相对 T 日收盘价的涨跌幅百分比 | | `T+1开盘是否盈利` | T+1 开盘收益大于 0 时为 `是`,否则为 `否`;无次日数据时为 `无次日数据` | diff --git a/internal/api/limit_second_profit_csv_handler.go b/internal/api/limit_second_profit_csv_handler.go index 55d34a4..4912426 100644 --- a/internal/api/limit_second_profit_csv_handler.go +++ b/internal/api/limit_second_profit_csv_handler.go @@ -28,6 +28,8 @@ type secondProfitCSVRow struct { Name string `gorm:"column:name"` Market string `gorm:"column:market"` Industry string `gorm:"column:industry"` + PreviousOpen sql.NullFloat64 `gorm:"column:previous_open"` + PreviousTwoClose sql.NullFloat64 `gorm:"column:previous_two_close"` Open sql.NullFloat64 `gorm:"column:open"` Close sql.NullFloat64 `gorm:"column:close_price"` LimitPrice float64 `gorm:"column:limit_price"` @@ -44,6 +46,7 @@ type secondProfitCSVRow struct { NextLow sql.NullFloat64 `gorm:"column:next_low"` NextClose sql.NullFloat64 `gorm:"column:next_close"` OpenPreviousCloseRatio float64 + PreviousOpenPctChg sql.NullFloat64 OpenPctChg sql.NullFloat64 NextOpenReturnPct sql.NullFloat64 NextHighReturnPct sql.NullFloat64 @@ -86,6 +89,7 @@ type secondProfitListItem struct { Name string `json:"name"` Market string `json:"market"` Industry string `json:"industry"` + PreviousOpenPctChg *float64 `json:"previous_open_pct_chg"` OpenPctChg *float64 `json:"open_pct_chg"` NextOpenPctChg *float64 `json:"next_open_pct_chg"` NextOpenProfitable string `json:"next_open_profitable"` @@ -323,6 +327,8 @@ SELECT COALESCE(l.name, '') AS name, COALESCE(l.market, '') AS market, COALESCE(l.tushare_industry, '') AS industry, + pd.open AS previous_open, + COALESCE(pd.pre_close, ppd.close) AS previous_two_close, d.open, COALESCE(l.calc_close, l.tushare_close, d.close) AS close_price, COALESCE(l.calc_limit_price, 0) AS limit_price, @@ -349,6 +355,8 @@ LEFT JOIN stock_daily d ON l.ts_code = d.ts_code AND d.trade_date = l.trade_date LEFT JOIN stock_daily pd ON l.ts_code = pd.ts_code AND pd.trade_date = c.previous_trade_date +LEFT JOIN stock_daily ppd + ON l.ts_code = ppd.ts_code AND ppd.trade_date = c.previous_two_trade_date LEFT JOIN stock_daily nd ON l.ts_code = nd.ts_code AND nd.trade_date = c.next_trade_date WHERE c.trade_date BETWEEN ? AND ? @@ -378,6 +386,12 @@ ORDER BY c.trade_date ASC, l.ts_code ASC` Valid: true, } } + if row.PreviousOpen.Valid && row.PreviousTwoClose.Valid && row.PreviousTwoClose.Float64 > 0 { + row.PreviousOpenPctChg = sql.NullFloat64{ + Float64: secondProfitRound2((row.PreviousOpen.Float64 - row.PreviousTwoClose.Float64) / row.PreviousTwoClose.Float64 * 100), + Valid: true, + } + } if req.OpenPctChgRule.Enabled() && (!row.OpenPctChg.Valid || !req.OpenPctChgRule.Match(row.OpenPctChg.Float64)) { continue } @@ -399,6 +413,7 @@ ORDER BY c.trade_date ASC, l.ts_code ASC` func secondProfitCSVHeaders() []string { return []string{ "交易日", "股票代码", "股票简称", "市场", "行业", + "T-1日开盘涨跌幅%", "T日开盘涨跌幅%", "T+1日开盘涨跌幅%", "T+1开盘是否盈利", "T+1收盘是否盈利", "T+1盘中是否可盈利", "T+1最高盈利%", "T+1最低盈利%", "开板次数", "换手率%", @@ -413,6 +428,7 @@ func secondProfitCSVRecord(row secondProfitCSVRow) []string { row.Name, row.Market, row.Industry, + secondProfitFormatNullFloat(row.PreviousOpenPctChg), secondProfitFormatNullFloat(row.OpenPctChg), secondProfitFormatNullFloat(row.NextOpenReturnPct), row.NextOpenProfitable, @@ -435,6 +451,7 @@ func secondProfitBuildItem(row secondProfitCSVRow) secondProfitListItem { Name: row.Name, Market: row.Market, Industry: row.Industry, + PreviousOpenPctChg: secondProfitNullFloatPtr(row.PreviousOpenPctChg), OpenPctChg: secondProfitNullFloatPtr(row.OpenPctChg), NextOpenPctChg: secondProfitNullFloatPtr(row.NextOpenReturnPct), NextOpenProfitable: row.NextOpenProfitable,