Skip to content

Commit

Permalink
格雷厄姆内在价值(感觉结果有问题。。)
Browse files Browse the repository at this point in the history
  • Loading branch information
axiaoxin committed Nov 22, 2021
1 parent 31d995e commit d8cf8ff
Show file tree
Hide file tree
Showing 12 changed files with 75 additions and 44 deletions.
3 changes: 2 additions & 1 deletion core/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,10 +335,11 @@ func (c Checker) CheckFundamentals(ctx context.Context, stock models.Stock) (res
itemOK = true
price := stock.GetPrice()
desc = fmt.Sprintf(
"最新股价:%f</br>合理价:%.2f(%.2f%%)</br>去年合理价:%.2f,去年实际价格:%.2f",
"最新股价:%f</br>合理价:%.2f(%.2f%%)</br>内在价值:%.2f</br>去年合理价:%.2f,去年实际价格:%.2f",
price,
stock.RightPrice,
stock.PriceSpace,
stock.IntrinsicalValue,
stock.LastYearRightPrice,
stock.HistoricalPrice.LastYearFinalPrice(),
)
Expand Down
4 changes: 2 additions & 2 deletions cron/bond.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (

"github.com/axiaoxin-com/goutils"
"github.com/axiaoxin-com/investool/datacenter"
"github.com/axiaoxin-com/investool/services"
"github.com/axiaoxin-com/investool/models"
)

// SyncBond 同步债券
Expand All @@ -15,5 +15,5 @@ func SyncBond() {
return
}
ctx := context.Background()
services.AAACompanyBondSyl = datacenter.ChinaBond.QueryAAACompanyBondSyl(ctx)
models.AAACompanyBondSyl = datacenter.ChinaBond.QueryAAACompanyBondSyl(ctx)
}
23 changes: 11 additions & 12 deletions cron/fund.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"github.com/axiaoxin-com/investool/datacenter"
"github.com/axiaoxin-com/investool/datacenter/eastmoney"
"github.com/axiaoxin-com/investool/models"
"github.com/axiaoxin-com/investool/services"
"github.com/axiaoxin-com/logging"
)

Expand Down Expand Up @@ -46,35 +45,35 @@ func SyncFund() {
}

// 更新 services 变量
services.FundAllList = fundlist
models.FundAllList = fundlist
fundtypes := []string{}
for k := range typeMap {
fundtypes = append(fundtypes, k)
}
services.FundTypeList = fundtypes
models.FundTypeList = fundtypes

// 更新文件
b, err := json.Marshal(efundlist)
if err != nil {
logging.Errorf(ctx, "SyncFund json marshal efundlist error:%v", err)
promSyncError.WithLabelValues("SyncFund").Inc()
} else if err := ioutil.WriteFile(services.RawFundAllListFilename, b, 0666); err != nil {
} else if err := ioutil.WriteFile(models.RawFundAllListFilename, b, 0666); err != nil {
logging.Errorf(ctx, "SyncFund WriteFile efundlist error:%v", err)
promSyncError.WithLabelValues("SyncFund").Inc()
}
b, err = json.Marshal(fundlist)
if err != nil {
logging.Errorf(ctx, "SyncFund json marshal fundlist error:%v", err)
promSyncError.WithLabelValues("SyncFund").Inc()
} else if err := ioutil.WriteFile(services.FundAllListFilename, b, 0666); err != nil {
} else if err := ioutil.WriteFile(models.FundAllListFilename, b, 0666); err != nil {
logging.Errorf(ctx, "SyncFund WriteFile fundlist error:%v", err)
promSyncError.WithLabelValues("SyncFund").Inc()
}
b, err = json.Marshal(services.FundTypeList)
b, err = json.Marshal(models.FundTypeList)
if err != nil {
logging.Errorf(ctx, "SyncFund json marshal fundtypelist error:%v", err)
promSyncError.WithLabelValues("SyncFund").Inc()
} else if err := ioutil.WriteFile(services.FundTypeListFilename, b, 0666); err != nil {
} else if err := ioutil.WriteFile(models.FundTypeListFilename, b, 0666); err != nil {
logging.Errorf(ctx, "SyncFund WriteFile fundtypelist error:%v", err)
promSyncError.WithLabelValues("SyncFund").Inc()
}
Expand All @@ -83,29 +82,29 @@ func SyncFund() {
Update4433()

// 更新同步时间
services.SyncFundTime = time.Now()
models.SyncFundTime = time.Now()
}

// Update4433 更新4433检测结果
func Update4433() {
ctx := context.Background()
fundlist := models.FundList{}
for _, fund := range services.FundAllList {
for _, fund := range models.FundAllList {
if fund.Is4433(ctx) {
fundlist = append(fundlist, fund)
}
}
// 更新 services 变量
// 更新 models 变量
fundlist.Sort(models.FundSortTypeWeek)
services.Fund4433List = fundlist
models.Fund4433List = fundlist

// 更新文件
b, err := json.Marshal(fundlist)
if err != nil {
logging.Errorf(ctx, "Update4433 json marshal error:", err)
promSyncError.WithLabelValues("Update4433").Inc()
return
} else if err := ioutil.WriteFile(services.Fund4433ListFilename, b, 0666); err != nil {
} else if err := ioutil.WriteFile(models.Fund4433ListFilename, b, 0666); err != nil {
logging.Errorf(ctx, "Update4433 WriteFile error:", err)
promSyncError.WithLabelValues("Update4433").Inc()
return
Expand Down
6 changes: 3 additions & 3 deletions cron/stock.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

"github.com/axiaoxin-com/goutils"
"github.com/axiaoxin-com/investool/datacenter"
"github.com/axiaoxin-com/investool/services"
"github.com/axiaoxin-com/investool/models"
"github.com/axiaoxin-com/logging"
)

Expand All @@ -24,7 +24,7 @@ func SyncIndustryList() {
promSyncError.WithLabelValues("SyncIndustryList").Inc()
return
}
services.StockIndustryList = indlist
models.StockIndustryList = indlist

// 更新文件
b, err := json.Marshal(indlist)
Expand All @@ -33,7 +33,7 @@ func SyncIndustryList() {
promSyncError.WithLabelValues("SyncIndustryList").Inc()
return
}
if err := ioutil.WriteFile(services.IndustryListFilename, b, 0666); err != nil {
if err := ioutil.WriteFile(models.IndustryListFilename, b, 0666); err != nil {
logging.Errorf(ctx, "SyncIndustryList WriteFile error:", err)
promSyncError.WithLabelValues("SyncIndustryList").Inc()
return
Expand Down
15 changes: 15 additions & 0 deletions datacenter/eastmoney/fina_main.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,21 @@ func (h HistoricalFinaMainData) GetAvgRevenueIncreasingRatioByYear(ctx context.C
return sum / float64(dlen)
}

// GetAvgEpsIncreasingRatioByYear 获取指定年内已发布的各期财报的平均EPS增长比 (%)
func (h HistoricalFinaMainData) GetAvgEpsIncreasingRatioByYear(ctx context.Context, year int) float64 {
data := h.FilterByReportYear(ctx, year)
dlen := len(data)
if dlen == 0 {
return 0
}
sum := 0.0
for _, d := range data {
sum += d.Epsjbtz
}

return sum / float64(dlen)
}

// RespFinaMainData 接口返回 json 结构
type RespFinaMainData struct {
Version string `json:"version"`
Expand Down
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"time"

"github.com/axiaoxin-com/investool/cmds"
"github.com/axiaoxin-com/investool/models"
"github.com/axiaoxin-com/investool/version"
"github.com/axiaoxin-com/logging"
"github.com/spf13/viper"
Expand All @@ -24,6 +25,7 @@ var (

func init() {
viper.SetDefault("app.chan_size", 50)
models.InitGlobalVars()
}

func main() {
Expand Down
3 changes: 3 additions & 0 deletions models/exportor_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ type ExportorData struct {
RightPrice interface{} `json:"right_price" csv:"估算合理价格"`
// 合理价格与当时价的价格差(%)
PriceSpace interface{} `json:"price_space" csv:"合理价差"`
// 内在价值
IntrinsicalValue float64 `json:"intrinsical_value" csv:"内在价值"`
// 历史波动率
HV float64 `json:"hv" csv:"历史波动率"`
// 最新负债率 (%)
Expand Down Expand Up @@ -217,6 +219,7 @@ func NewExportorData(ctx context.Context, stock Stock) ExportorData {
Price: stock.GetPrice(),
RightPrice: rightPrice,
PriceSpace: priceSpace,
IntrinsicalValue: stock.IntrinsicalValue,
HV: stock.HistoricalVolatility,
ListingVolatilityYear: stock.BaseInfo.ListingVolatilityYear,
ZXFZL: fina.Zcfzl,
Expand Down
30 changes: 24 additions & 6 deletions services/global.go → models/global.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Package services 加载或初始化外部依赖服务
package services
// Package models
// 全局变量

package models

import (
"context"
Expand All @@ -8,7 +10,7 @@ import (
"time"

"github.com/axiaoxin-com/investool/datacenter"
"github.com/axiaoxin-com/investool/models"
"github.com/axiaoxin-com/logging"
)

var (
Expand All @@ -19,9 +21,9 @@ var (
// Fund4433TypeList 4433基金类型列表
Fund4433TypeList []string
// FundAllList 全量基金列表
FundAllList models.FundList
FundAllList FundList
// Fund4433List 满足4433法则的基金列表
Fund4433List models.FundList
Fund4433List FundList
// SyncFundTime 基金数据同步时间
SyncFundTime = time.Now()
// RawFundAllListFilename api返回的原始结果
Expand All @@ -38,6 +40,22 @@ var (
AAACompanyBondSyl = datacenter.ChinaBond.QueryAAACompanyBondSyl(context.Background())
)

// InitGlobalVars 初始化全局变量
func InitGlobalVars() {
if err := InitIndustryList(); err != nil {
logging.Error(nil, "init models global vars error:"+err.Error())
}
if err := InitFundAllList(); err != nil {
logging.Error(nil, "init models global vars error:"+err.Error())
}
if err := InitFund4433List(); err != nil {
logging.Error(nil, "init models global vars error:"+err.Error())
}
if err := InitFundTypeList(); err != nil {
logging.Error(nil, "init models global vars error:"+err.Error())
}
}

// InitIndustryList 初始化行业列表
func InitIndustryList() error {
indlist, err := datacenter.EastMoney.QueryIndustryList(context.Background())
Expand Down Expand Up @@ -66,7 +84,7 @@ func InitFund4433List() error {
if err := json.Unmarshal(fundlist, &Fund4433List); err != nil {
return err
}
Fund4433List.Sort(models.FundSortTypeWeek)
Fund4433List.Sort(FundSortTypeWeek)
Fund4433TypeList = Fund4433List.Types()
return nil
}
Expand Down
7 changes: 7 additions & 0 deletions models/stock.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ type Stock struct {
HistoricalPEList eastmoney.HistoricalPEList `json:"historical_pe_list"`
// 合理价格(年报):历史市盈率中位数 * (去年EPS * (1 + 今年各期财报的平均营收增长比))
RightPrice float64 `json:"right_price"`
// 格雷厄姆内在价值
IntrinsicalValue float64 `json:"intrinsical_value"`
// 合理价差(%)
PriceSpace float64 `json:"price_space"`
// 按前年年报算去年的合理价格:历史市盈率中位数 * (前年EPS * (1 + 去年各期财报的平均营收增长比))
Expand Down Expand Up @@ -168,6 +170,11 @@ func NewStock(ctx context.Context, baseInfo eastmoney.StockInfo) (Stock, error)
beforeLastYearReport := s.HistoricalFinaMainData.GetReport(ctx, time.Now().Year()-2, eastmoney.FinaReportTypeYear)
lastYearAvgRevIncrRatio := s.HistoricalFinaMainData.GetAvgRevenueIncreasingRatioByYear(ctx, thisYear-1)
s.LastYearRightPrice = peMidVal * (beforeLastYearReport.Epsjb * (1 + lastYearAvgRevIncrRatio/100.0))
// 内在价值 E*(2r+8.5)*4.4/Y
if AAACompanyBondSyl != 0 {
thisYearAvgEpsIncrRatio := s.HistoricalFinaMainData.GetAvgEpsIncreasingRatioByYear(ctx, thisYear)
s.IntrinsicalValue = lastYearReport.Epsjb * (2*thisYearAvgEpsIncrRatio + 8.5) * 4.4 / AAACompanyBondSyl
}
}(ctx, &s)

// 获取综合估值
Expand Down
11 changes: 5 additions & 6 deletions routes/fund.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"github.com/axiaoxin-com/goutils"
"github.com/axiaoxin-com/investool/core"
"github.com/axiaoxin-com/investool/models"
"github.com/axiaoxin-com/investool/services"
"github.com/axiaoxin-com/investool/version"
"github.com/axiaoxin-com/logging"
"github.com/gin-gonic/gin"
Expand All @@ -26,7 +25,7 @@ type ParamFundIndex struct {

// FundIndex godoc
func FundIndex(c *gin.Context) {
fundList := services.Fund4433List
fundList := models.Fund4433List
p := ParamFundIndex{
PageNum: 1,
PageSize: 10,
Expand Down Expand Up @@ -63,10 +62,10 @@ func FundIndex(c *gin.Context) {
"FundList": result,
"Pagination": pagi,
"IndexParam": p,
"UpdatedAt": services.SyncFundTime.Format("2006-01-02 15:04:05"),
"AllFundCount": len(services.FundAllList),
"UpdatedAt": models.SyncFundTime.Format("2006-01-02 15:04:05"),
"AllFundCount": len(models.FundAllList),
"Fund4433Count": totalCount,
"FundTypes": services.Fund4433TypeList,
"FundTypes": models.Fund4433TypeList,
}
c.HTML(http.StatusOK, "fund_index.html", data)
return
Expand Down Expand Up @@ -107,7 +106,7 @@ func FundFilter(c *gin.Context) {
c.HTML(http.StatusOK, "fund_filter.html", data)
return
}
fundList := services.FundAllList.Filter(c, p.ParamFundListFilter)
fundList := models.FundAllList.Filter(c, p.ParamFundListFilter)
fundTypes := fundList.Types()
// 过滤
if p.ParamFundIndex.Type != "" {
Expand Down
3 changes: 1 addition & 2 deletions routes/stock.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"github.com/axiaoxin-com/investool/core"
"github.com/axiaoxin-com/investool/datacenter/eastmoney"
"github.com/axiaoxin-com/investool/models"
"github.com/axiaoxin-com/investool/services"
"github.com/axiaoxin-com/investool/version"
"github.com/gin-gonic/gin"
"github.com/spf13/viper"
Expand All @@ -26,7 +25,7 @@ func StockIndex(c *gin.Context) {
"Version": version.Version,
"PageTitle": "InvesTool | 股票",
"Error": "",
"IndustryList": services.StockIndustryList,
"IndustryList": models.StockIndustryList,
}
c.HTML(http.StatusOK, "stock_index.html", data)
return
Expand Down
12 changes: 0 additions & 12 deletions services/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,5 @@ package services

// Init 相关依赖服务的初始化或加载操作
func Init() error {
if err := InitIndustryList(); err != nil {
return err
}
if err := InitFundAllList(); err != nil {
return err
}
if err := InitFund4433List(); err != nil {
return err
}
if err := InitFundTypeList(); err != nil {
return err
}
return nil
}

0 comments on commit d8cf8ff

Please sign in to comment.