Skip to content

Commit

Permalink
筛选结果输出主力资金净流入
Browse files Browse the repository at this point in the history
  • Loading branch information
axiaoxin committed Jul 18, 2021
1 parent cb6e296 commit 830fbb3
Show file tree
Hide file tree
Showing 9 changed files with 226 additions and 9 deletions.
4 changes: 4 additions & 0 deletions datacenter/datacenter.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/axiaoxin-com/x-stock/datacenter/eastmoney"
"github.com/axiaoxin-com/x-stock/datacenter/eniu"
"github.com/axiaoxin-com/x-stock/datacenter/sina"
"github.com/axiaoxin-com/x-stock/datacenter/zszx"
)

var (
Expand All @@ -14,10 +15,13 @@ var (
Eniu eniu.Eniu
// Sina 新浪财经
Sina sina.Sina
// Zszx 招商证券
Zszx zszx.Zszx
)

func init() {
EastMoney = eastmoney.NewEastMoney()
Eniu = eniu.NewEniu()
Sina = sina.NewSina()
Zszx = zszx.NewZszx()
}
102 changes: 102 additions & 0 deletions datacenter/zszx/net_inflows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// 获取个股指定时间段内资金净流入数据

package zszx

import (
"context"
"errors"
"fmt"
"strconv"
"strings"
"time"

"github.com/axiaoxin-com/goutils"
"github.com/axiaoxin-com/logging"
"go.uber.org/zap"
)

// NetInflow 资金净流入详情
type NetInflow struct {
// 交易日期
TrdDt string `json:"TrdDt"`
// 当日股价
ClsPrc string `json:"ClsPrc"`
// 主力净流入(万元)
MainMnyNetIn string `json:"MainMnyNetIn"`
// 超大单净流入(万元)
HugeNetIn string `json:"HugeNetIn"`
// 大单净流入(万元)
BigNetIn string `json:"BigNetIn"`
// 中单净流入(万元)
MidNetIn string `json:"MidNetIn"`
// 小单净流入(万元)
SmallNetIn string `json:"SmallNetIn"`
TTLMnyNetIn string `json:"TtlMnyNetIn"`
}

// NetInflowList 净流入详情列表
type NetInflowList []NetInflow

// SumMainNetIn 主力净流入列表求和
func (n NetInflowList) SumMainNetIn(ctx context.Context) float64 {
var netFlowin float64 = 0.0
for _, i := range n {
mainNetIn, err := strconv.ParseFloat(i.MainMnyNetIn, 64)
if err != nil {
logging.Errorf(ctx, "Parse MainMnyNetIn:%v to Float error:%v", i.MainMnyNetIn, err)
}
netFlowin += mainNetIn
}
return netFlowin
}

// RespMainMoneyNetInflows QueryMainMoneyNetInflows 返回json结构
type RespMainMoneyNetInflows struct {
Success bool `json:"success"`
Message string `json:"message"`
Code int `json:"code"`
Data NetInflowList `json:"data"`
}

// QueryMainMoneyNetInflows 查询主力资金净流入数据
func (z Zszx) QueryMainMoneyNetInflows(ctx context.Context, secuCode, startDate, endDate string) (NetInflowList, error) {
apiurl := "https://zszx.cmschina.com/pcnews/f10/stkcnmnyflow"
stockCodeAndMarket := strings.Split(secuCode, ".")
if len(stockCodeAndMarket) != 2 {
return nil, errors.New("invalid secuCode:" + secuCode)
}
stockCode := stockCodeAndMarket[0]
market := stockCodeAndMarket[1]
marketCode := "0"
if strings.ToUpper(market) == "SH" {
marketCode = "1"
}
params := map[string]string{
"dateStart": startDate,
"dateEnd": endDate,
"ecode": marketCode,
"scode": stockCode,
}
logging.Debug(ctx, "Zszx QueryMainMoneyNetInflows "+apiurl+" begin", zap.Any("params", params))
beginTime := time.Now()
apiurl, err := goutils.NewHTTPGetURLWithQueryString(ctx, apiurl, params)
if err != nil {
return nil, err
}
resp := RespMainMoneyNetInflows{}
err = goutils.HTTPGET(ctx, z.HTTPClient, apiurl, &resp)
latency := time.Now().Sub(beginTime).Milliseconds()
logging.Debug(
ctx,
"Zszx QueryMainMoneyNetInflows "+apiurl+" end",
zap.Int64("latency(ms)", latency),
zap.Any("resp", resp),
)
if err != nil {
return nil, err
}
if resp.Code != 0 {
return nil, fmt.Errorf("%s %#v", secuCode, resp)
}
return resp.Data, nil
}
26 changes: 26 additions & 0 deletions datacenter/zszx/net_inflows_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package zszx

import (
"testing"
"time"

"github.com/stretchr/testify/require"
)

func TestQueryMainMoneyNetInflows(t *testing.T) {
now := time.Now()
end := now.Format("2006-01-02")
d, _ := time.ParseDuration("-720h")
start := now.Add(d).Format("2006-01-02")
results, err := _z.QueryMainMoneyNetInflows(_ctx, "002028.sz", start, end)
require.Nil(t, err)
require.NotEqual(t, len(results), 0)
last3days := results[:3]
t.Logf("last3days:%#v, sum:%f", last3days, last3days.SumMainNetIn(_ctx))
last5days := results[:5]
t.Logf("last5days:%#v, sum:%f", last5days, last5days.SumMainNetIn(_ctx))
last10days := results[:10]
t.Logf("last10days:%#v, sum:%f", last10days, last10days.SumMainNetIn(_ctx))
last20days := results[:20]
t.Logf("last20days:%#v, sum:%f", last20days, last20days.SumMainNetIn(_ctx))
}
24 changes: 24 additions & 0 deletions datacenter/zszx/zszx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Package zszx 招商证券接口封装
// https://zszx.cmschina.com/
package zszx

import (
"net/http"
"time"
)

// Zszx 招商证券接口
type Zszx struct {
// http 客户端
HTTPClient *http.Client
}

// NewZszx 创建 Zszx 实例
func NewZszx() Zszx {
hc := &http.Client{
Timeout: time.Second * 60 * 5,
}
return Zszx{
HTTPClient: hc,
}
}
10 changes: 10 additions & 0 deletions datacenter/zszx/zszx_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package zszx

import (
"context"
)

var (
_z = NewZszx()
_ctx = context.TODO()
)
36 changes: 30 additions & 6 deletions models/exportor_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package models

import (
"context"
"fmt"
"sort"
"strings"

Expand Down Expand Up @@ -123,6 +124,8 @@ type ExportorData struct {
NetcashFree string `json:"netcash_free" csv:"自由现金流"`
// 十大流通股东
FreeHoldersTop10 string `json:"free_holders_top_10" csv:"十大流通股东"`
// 主力净流入
MainMoneyNetInflows string `json:"main_money_net_inflows" csv:"主力资金净流入"`
}

// GetHeaderValueMap 获取以 csv tag 为 key 的 Data map
Expand Down Expand Up @@ -166,6 +169,26 @@ func NewExportorData(ctx context.Context, stock Stock) ExportorData {
if len(stock.HistoricalFinaMainData) == 0 {
return ExportorData{}
}

netInflowsLen := len(stock.MainMoneyNetInflows)
netInflow3days := "--"
if netInflowsLen >= 3 {
netInflow3days = fmt.Sprintf("近3日主力资金净流入:%.2f万元", stock.MainMoneyNetInflows[:3].SumMainNetIn(ctx))
}
netInflow5days := "--"
if netInflowsLen >= 5 {
netInflow5days = fmt.Sprintf("近5日主力资金净流入:%.2f万元", stock.MainMoneyNetInflows[:5].SumMainNetIn(ctx))
}
netInflow10days := "--"
if netInflowsLen >= 10 {
netInflow10days = fmt.Sprintf("近10日主力资金净流入:%.2f万元", stock.MainMoneyNetInflows[:10].SumMainNetIn(ctx))
}
netInflow20days := "--"
if netInflowsLen >= 20 {
netInflow20days = fmt.Sprintf("近20日主力资金净流入:%.2f万元", stock.MainMoneyNetInflows[:20].SumMainNetIn(ctx))
}
mainNetInflows := fmt.Sprintf("%s</br>%s</br>%s</br>%s", netInflow3days, netInflow5days, netInflow10days, netInflow20days)

fina := stock.HistoricalFinaMainData[0]
return ExportorData{
Name: stock.BaseInfo.SecurityNameAbbr,
Expand Down Expand Up @@ -234,12 +257,13 @@ func NewExportorData(ctx context.Context, stock Stock) ExportorData {
),
JLL5Y: stock.HistoricalFinaMainData.ValueList(ctx, eastmoney.ValueListTypeJLL, 5, eastmoney.FinaReportTypeYear),

ListingDate: stock.BaseInfo.ListingDate,
NetcashOperate: goutils.YiWanString(stock.NetcashOperate),
NetcashInvest: goutils.YiWanString(stock.NetcashInvest),
NetcashFinance: goutils.YiWanString(stock.NetcashFinance),
NetcashFree: goutils.YiWanString(stock.NetcashFree),
FreeHoldersTop10: stock.FreeHoldersTop10.String(),
ListingDate: stock.BaseInfo.ListingDate,
NetcashOperate: goutils.YiWanString(stock.NetcashOperate),
NetcashInvest: goutils.YiWanString(stock.NetcashInvest),
NetcashFinance: goutils.YiWanString(stock.NetcashFinance),
NetcashFree: goutils.YiWanString(stock.NetcashFree),
FreeHoldersTop10: stock.FreeHoldersTop10.String(),
MainMoneyNetInflows: mainNetInflows,
}
}

Expand Down
26 changes: 24 additions & 2 deletions models/stock.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import (
"context"
"sort"
"sync"
"time"

"github.com/axiaoxin-com/logging"
"github.com/axiaoxin-com/x-stock/datacenter"
"github.com/axiaoxin-com/x-stock/datacenter/eastmoney"
"github.com/axiaoxin-com/x-stock/datacenter/eniu"
"github.com/axiaoxin-com/x-stock/datacenter/zszx"
)

// Stock 接口返回的股票信息结构
Expand Down Expand Up @@ -63,6 +65,8 @@ type Stock struct {
NetcashFree float64 `json:"netcash_free"`
// 十大流通股东
FreeHoldersTop10 eastmoney.FreeHolderList `json:"free_holders_top_10"`
// 主力资金净流入
MainMoneyNetInflows zszx.NetInflowList `json:"main_money_net_inflows"`
}

// GetPrice 返回股价,没开盘时可能是字符串“-”,此时返回最近历史股价,无历史价则返回 -1
Expand Down Expand Up @@ -219,7 +223,7 @@ func NewStock(ctx context.Context, baseInfo eastmoney.StockInfo) (Stock, error)
}()
orgRatings, err := datacenter.EastMoney.QueryOrgRating(ctx, s.BaseInfo.Secucode)
if err != nil {
logging.Error(ctx, "NewStock QueryOrgRating err:"+err.Error())
logging.Warn(ctx, "NewStock QueryOrgRating err:"+err.Error())
return
}
s.OrgRatingList = orgRatings
Expand All @@ -233,7 +237,7 @@ func NewStock(ctx context.Context, baseInfo eastmoney.StockInfo) (Stock, error)
}()
pps, err := datacenter.EastMoney.QueryProfitPredict(ctx, s.BaseInfo.Secucode)
if err != nil {
logging.Error(ctx, "NewStock QueryProfitPredict err:"+err.Error())
logging.Warn(ctx, "NewStock QueryProfitPredict err:"+err.Error())
return
}
s.ProfitPredictList = pps
Expand Down Expand Up @@ -316,6 +320,24 @@ func NewStock(ctx context.Context, baseInfo eastmoney.StockInfo) (Stock, error)
s.FreeHoldersTop10 = holders
}(ctx, s)

// 获取最近30日的主力资金净流入
wg.Add(1)
go func(ctx context.Context, s *Stock) {
defer func() {
wg.Done()
}()
now := time.Now()
end := now.Format("2006-01-02")
d, _ := time.ParseDuration("-720h")
start := now.Add(d).Format("2006-01-02")
inflows, err := datacenter.Zszx.QueryMainMoneyNetInflows(ctx, s.BaseInfo.Secucode, start, end)
if err != nil {
logging.Error(ctx, "NewStock QueryMainMoneyNetInflows err:"+err.Error())
return
}
s.MainMoneyNetInflows = inflows
}(ctx, s)

wg.Wait()

return *s, nil
Expand Down
2 changes: 2 additions & 0 deletions statics/html/stock_index.html
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ <h4 class="center">筛选结果</h4>
<li><label><input id="sf_51" type="checkbox" /><span>筹资现金流净额</span></label></li>
<li><label><input id="sf_52" type="checkbox" /><span>自由现金流</span></label></li>
<li><label><input id="sf_53" type="checkbox" /><span>十大流通股东</span></label></li>
<li><label><input id="sf_54" type="checkbox" /><span>主力资金净流入</span></label></li>
</ul>
</div>
<div class="divider"></div>
Expand Down Expand Up @@ -385,6 +386,7 @@ <h4 class="center">筛选结果</h4>
<th class="hide st_51">筹资现金流净额</th>
<th class="hide st_52">自由现金流</th>
<th class="hide st_53">十大流通股东</th>
<th class="hide st_54">主力资金净流入</th>
</tr>
</thead>
<tbody>
Expand Down
5 changes: 4 additions & 1 deletion statics/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,9 @@ $(document).ready(function () {
'<td class="hide st_53">' +
stock.free_holders_top_10 +
"</td>" +
'<td class="hide st_54">' +
stock.main_money_net_inflows +
"</td>" +
"</tr>"
);
});
Expand Down Expand Up @@ -401,7 +404,7 @@ $(document).ready(function () {
$(".dropdown-content>li>a").css("font-size", "11px");
$(".dropdown-content>li>a").css("font-weight", "normal");

for (let i = 1; i <= 53; i++) {
for (let i = 1; i <= 54; i++) {
$(`#sf_${i}`).change(function () {
checkboxCountCheck();
$(`.st_${i}`).toggleClass("hide");
Expand Down

0 comments on commit 830fbb3

Please sign in to comment.