Skip to content

Commit

Permalink
filter managers
Browse files Browse the repository at this point in the history
  • Loading branch information
axiaoxin committed Dec 12, 2021
1 parent 7a3d1bb commit 6355670
Show file tree
Hide file tree
Showing 10 changed files with 207 additions and 10 deletions.
8 changes: 7 additions & 1 deletion cron/fund_managers.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/axiaoxin-com/goutils"
"github.com/axiaoxin-com/investool/datacenter"
"github.com/axiaoxin-com/investool/datacenter/eastmoney"
"github.com/axiaoxin-com/investool/models"
"github.com/axiaoxin-com/logging"
)
Expand All @@ -22,8 +23,13 @@ func SyncFundManagers() {
if err != nil {
logging.Error(ctx, "SyncFundManagers error:"+err.Error())
}

if len(managers) != 0 {
models.FundManagers = managers
models.FundManagers = managers.Filter(ctx, eastmoney.ParamFundManagerFilter{
MinWorkingYears: 8,
MinYieldse: 15.0,
MaxCurrentFundCount: 10,
})
}

// 更新文件
Expand Down
1 change: 1 addition & 0 deletions cron/fund_managers.json

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions cron/fund_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,9 @@ func _TestSyncFund(t *testing.T) {
viper.SetDefault("app.chan_size", 500)
SyncFund()
}

func TestSyncFundManagers(t *testing.T) {
logging.SetLevel("warn")
viper.SetDefault("app.chan_size", 500)
SyncFundManagers()
}
94 changes: 94 additions & 0 deletions datacenter/eastmoney/fund_manager_base_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package eastmoney

import (
"context"
"errors"
"fmt"
"time"

Expand Down Expand Up @@ -69,6 +70,7 @@ func (e EastMoney) FundMangerBaseList(ctx context.Context, mftype string, sortCo
header := map[string]string{
"user-agent": uarand.GetRandom(),
}
// TODO: 并发优化
result := []*FundManagerBaseInfo{}
index := 1
size := 300
Expand Down Expand Up @@ -102,3 +104,95 @@ func (e EastMoney) FundMangerBaseList(ctx context.Context, mftype string, sortCo
)
return result, nil
}

// RespFundMsnManagerInfo FundMsnManagerInfo接口返回结构
type RespFundMsnManagerInfo struct {
Datas struct {
Mgrid string `json:"MGRID"`
Mgrname string `json:"MGRNAME"`
Resume string `json:"RESUME"`
Investmentmethod string `json:"INVESTMENTMETHOD"`
Investmentidear string `json:"INVESTMENTIDEAR"`
Totaldays string `json:"TOTALDAYS"`
Netnav string `json:"NETNAV"`
Fcount string `json:"FCOUNT"`
Tcount string `json:"TCOUNT"`
Precode string `json:"PRECODE"`
Prename string `json:"PRENAME"`
Awardnum string `json:"AWARDNUM"`
Iswxpj string `json:"ISWXPJ"`
Pf3 string `json:"PF_3"`
Yj3 string `json:"YJ_3"`
Maxpenavgrowth string `json:"MAXPENAVGROWTH"`
Yieldse string `json:"YIELDSE"`
Jjgs string `json:"JJGS"`
Jjgsid string `json:"JJGSID"`
Newphotourl string `json:"NEWPHOTOURL"`
Mftype string `json:"MFTYPE"`
AwardnumJn string `json:"AWARDNUM_JN"`
AwardnumMx string `json:"AWARDNUM_MX"`
Awardfnum string `json:"AWARDFNUM"`
Fcode string `json:"FCODE"`
Shortname string `json:"SHORTNAME"`
Maxretra1 string `json:"MAXRETRA1"`
Maxearn1 string `json:"MAXEARN1"`
Fmaxearn1 string `json:"FMAXEARN1"`
Fmaxretra1 string `json:"FMAXRETRA1"`
Sex string `json:"SEX"`
Wins []struct {
Fcode string `json:"FCODE"`
Shortname string `json:"SHORTNAME"`
Awardfullname string `json:"AWARDFULLNAME"`
Awardname string `json:"AWARDNAME"`
Noticedate string `json:"NOTICEDATE"`
} `json:"WINS"`
Mgold string `json:"MGOLD"`
Sday string `json:"SDAY"`
Sct1 string `json:"SCT1"`
Sstd1 string `json:"SSTD1"`
Srt1 string `json:"SRT1"`
Sy1 string `json:"SY1"`
Sinfo1 string `json:"SINFO1"`
Strk1 string `json:"STRK1"`
Snav string `json:"SNAV"`
Sgr string `json:"SGR"`
} `json:"Datas"`
ErrCode int `json:"ErrCode"`
Success bool `json:"Success"`
ErrMsg interface{} `json:"ErrMsg"`
Message interface{} `json:"Message"`
ErrorCode string `json:"ErrorCode"`
ErrorMessage interface{} `json:"ErrorMessage"`
ErrorMsgLst interface{} `json:"ErrorMsgLst"`
TotalCount int `json:"TotalCount"`
Expansion interface{} `json:"Expansion"`
}

// QueryFundMsnMangerInfo 查询基金经理信息(app接口)
func (e EastMoney) QueryFundMsnMangerInfo(ctx context.Context, mgrid string) (*RespFundMsnManagerInfo, error) {
beginTime := time.Now()
resp := &RespFundMsnManagerInfo{}
apiurl := fmt.Sprintf(
"https://fundztapi.eastmoney.com/FundSpecialApiNew/FundMSNMangerInfo?FCODE=%s&plat=Iphone&deviceid=123&product=EFund&version=6.4.7",
mgrid,
)
logging.Debug(ctx, "EastMoney QueryFundMsnMangerInfo "+apiurl+" begin")
header := map[string]string{
"user-agent": uarand.GetRandom(),
}
if err := goutils.HTTPGET(ctx, e.HTTPClient, apiurl, header, resp); err != nil {
return nil, err
}
latency := time.Now().Sub(beginTime).Milliseconds()
logging.Debug(
ctx,
"EastMoney QueryFundMsnMangerInfo end",
zap.Int64("latency(ms)", latency),
)

if resp.ErrCode != 0 {
return nil, errors.New(resp.ErrMsg.(string))
}

return resp, nil
}
9 changes: 9 additions & 0 deletions datacenter/eastmoney/fund_manager_base_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,12 @@ func TestFundManagerBaseList(t *testing.T) {
_, err = json.Marshal(data)
require.Nil(t, err)
}

func TestFundMsnManagerInfo(t *testing.T) {
data, err := _em.QueryFundMsnMangerInfo(_ctx, "30040544")
require.Nil(t, err)
require.NotEmpty(t, data)
t.Logf("data:%+v", data)
_, err = json.Marshal(data)
require.Nil(t, err)
}
42 changes: 39 additions & 3 deletions datacenter/eastmoney/fund_managers.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,41 @@ type FundManagerInfo struct {
CurrentBestFundName string `json:"current_best_fund_name"`
// 现任基金资产总规模(亿元)
CurrentFundScale float64 `json:"current_fund_scale"`
// 任职期间最佳基金回报
// 任职期间最佳基金回报(%)
WorkingBestReturn float64 `json:"working_best_return"`
// 年化回报(%)
Yieldse float64 `json:"yieldse"`
}

// FundManagerInfoList 基金经理列表
type FundManagerInfoList []*FundManagerInfo

// ParamFundManagerFilter 基金列表过滤参数
type ParamFundManagerFilter struct{}
type ParamFundManagerFilter struct {
// 最低从业年限
MinWorkingYears int `json:"min_working_years"`
// 最低年化回报(%)
MinYieldse float64 `json:"min_yieldse"`
// 最大现任基金数量
MaxCurrentFundCount int `json:"max_current_fund_count"`
}

// Filter 按条件过滤列表
func (f FundManagerInfoList) Filter(ctx context.Context, p ParamFundManagerFilter) FundManagerInfoList {
return nil
result := FundManagerInfoList{}
for _, i := range f {
if i.WorkingDays/365 < p.MinWorkingYears {
continue
}
if i.Yieldse < p.MinYieldse {
continue
}
if len(i.CurrentBestFundCode) > p.MaxCurrentFundCount {
continue
}
result = append(result, i)
}
return result
}

// FundMangers 查询基金经理列表(web接口)
Expand All @@ -65,6 +87,7 @@ func (e EastMoney) FundMangers(ctx context.Context, ft, sc, st string) (FundMana
header := map[string]string{
"user-agent": uarand.GetRandom(),
}
// TODO: 并发优化
result := []*FundManagerInfo{}
index := 1
for {
Expand Down Expand Up @@ -136,6 +159,18 @@ func (e EastMoney) FundMangers(ctx context.Context, ft, sc, st string) (FundMana
logging.Warnf(ctx, "parse bestReturn:%v to float64 error:%v", wbestReturnNum, err)
}
}
yieldse := 0.0
info, err := e.QueryFundMsnMangerInfo(ctx, fields[0][1])
if err != nil {
logging.Error(ctx, "QueryFundMsnMangerInfo err:"+err.Error())
} else {
if info.Datas.Yieldse != "" && info.Datas.Yieldse != "--" {
yieldse, err = strconv.ParseFloat(info.Datas.Yieldse, 64)
if err != nil {
logging.Warnf(ctx, "parse yieldse:%v to float64 error:%v", info.Datas.Yieldse, err)
}
}
}
result = append(result, &FundManagerInfo{
ID: fields[0][1],
Name: fields[1][1],
Expand All @@ -149,6 +184,7 @@ func (e EastMoney) FundMangers(ctx context.Context, ft, sc, st string) (FundMana
CurrentBestFundName: fields[9][1],
CurrentFundScale: scale,
WorkingBestReturn: wbestReturn,
Yieldse: yieldse,
})
}
index++
Expand Down
12 changes: 10 additions & 2 deletions datacenter/eastmoney/fund_managers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,19 @@ import (
"github.com/stretchr/testify/require"
)

func TestFundManagers(t *testing.T) {
func _TestFundManagers(t *testing.T) {
data, err := _em.FundMangers(_ctx, "all", "penavgrowth", "desc")
require.Nil(t, err)
require.NotEmpty(t, data)
t.Logf("data:%+v", data)
// t.Logf("data:%+v\n", data)
_, err = json.Marshal(data)
require.Nil(t, err)
fd := data.Filter(_ctx, ParamFundManagerFilter{
MinWorkingYears: 8,
MinYieldse: 15.0,
MaxCurrentFundCount: 10,
})
for _, d := range fd {
t.Logf("d:%+v\n", *d)
}
}
4 changes: 1 addition & 3 deletions models/global.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
package models

import (
"context"
"encoding/json"
"io/ioutil"
"time"

"github.com/axiaoxin-com/investool/datacenter"
"github.com/axiaoxin-com/investool/datacenter/eastmoney"
"github.com/axiaoxin-com/logging"
)
Expand Down Expand Up @@ -42,7 +40,7 @@ var (
// FundManagersFilename 基金经理数据文件
FundManagersFilename = "./fund_managers.json"
// AAACompanyBondSyl AAA公司债当期收益率
AAACompanyBondSyl = datacenter.ChinaBond.QueryAAACompanyBondSyl(context.Background())
AAACompanyBondSyl = -1.0 // datacenter.ChinaBond.QueryAAACompanyBondSyl(context.Background())
)

// InitGlobalVars 初始化全局变量
Expand Down
2 changes: 1 addition & 1 deletion routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ func Routes(app *gin.Engine) {
app.GET("/fund/similarity", FundSimilarity)
app.GET("/materials", Materials)
app.POST("/fund/query_by_stock", QueryFundByStock)
app.POST("/fund/manager", FundManagers)
app.GET("/fund/managers", FundManagers)
}
39 changes: 39 additions & 0 deletions statics/html/fund_managers.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{{ template "header" . }}
<div class="col s12">
<h4 class="center">基金经理查询结果</h4>
<p class="tiny center">以下所有数据与信息仅供参考,不构成投资建议</p>
<div>
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3022214826355647"
crossorigin="anonymous"></script>
<ins class="adsbygoogle"
style="display:block"
data-ad-format="fluid"
data-ad-layout-key="-fb+5w+4e-db+86"
data-ad-client="ca-pub-3022214826355647"
data-ad-slot="6583498372"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
</div>
<div class="divider"></div>
<table class="striped centered">
<tbody>
{{ range .Managers }}
<tr>
<td>
<span class="copybtn waves-effect waves-red" data-clipboard-text="{{ .Fcode }}">
<a target="_blank" href="http://fund.eastmoney.com/{{ .ID }}.html">{{ .Name }}</a>
<i class="material-icons tiny">content_copy</i>
</span>
</td>
<td>年化回报:{{ .Yieldse }}%</td>
<td>任职期间最佳基金回报:{{ .WorkingBestReturn }}%</td>
<td>现任最佳基金:{{ .CurrentBestFundName }}({{ .CurrentBestFundCode }})%</td>
</tr>
{{ else }}
<th><td>没有找到同时持仓指定股票的基金</td></th>
{{ end }}
</tbody>
</table>
</div>
{{ template "footer" . }}

0 comments on commit 6355670

Please sign in to comment.