226 lines
5.3 KiB
Go
226 lines
5.3 KiB
Go
|
package moneymoney
|
||
|
|
||
|
import (
|
||
|
"hash"
|
||
|
"log"
|
||
|
"sort"
|
||
|
"time"
|
||
|
|
||
|
"github.com/474420502/random"
|
||
|
"github.com/474420502/structure/tree/treelist"
|
||
|
"github.com/davecgh/go-spew/spew"
|
||
|
)
|
||
|
|
||
|
func HistoryRun() {
|
||
|
|
||
|
rd := random.New()
|
||
|
|
||
|
var money float64 = 1000000.0
|
||
|
cday := GetDate("2017-05-01")
|
||
|
|
||
|
p := &Policy{
|
||
|
MarketValue: &RangeValue[float64]{MinLimt: 10, MaxLimit: 20000, Step: 1},
|
||
|
UpsDownsRatioDays: []*RangeValue[float64]{{MinLimt: 0, MaxLimit: 0.2, Step: 0.01}, {MinLimt: 0, MaxLimit: 0.3, Step: 0.01}, {MinLimt: 0, MaxLimit: 0.5, Step: 0.01}, {MinLimt: 0, MaxLimit: 0.5, Step: 0.01}},
|
||
|
UpsCount: &RangeValue[int]{MinLimt: 0, MaxLimit: 100, Step: 1},
|
||
|
DownsCount: &RangeValue[int]{MinLimt: 0, MaxLimit: 100, Step: 1},
|
||
|
MaxPriceRatio: &RangeValue[float64]{MinLimt: 0, MaxLimit: 1, Step: 0.01},
|
||
|
MinPriceRatio: &RangeValue[float64]{MinLimt: 0, MaxLimit: 1, Step: 0.01},
|
||
|
}
|
||
|
|
||
|
RESET:
|
||
|
for {
|
||
|
|
||
|
RandomRange(rd, p.MarketValue)
|
||
|
for _, rv := range p.UpsDownsRatioDays {
|
||
|
RandomRange(rd, rv)
|
||
|
}
|
||
|
RandomRange(rd, p.UpsCount)
|
||
|
RandomRange(rd, p.DownsCount)
|
||
|
RandomRange(rd, p.MaxPriceRatio)
|
||
|
RandomRange(rd, p.MinPriceRatio)
|
||
|
spew.Println(p)
|
||
|
|
||
|
ALL_LOOP:
|
||
|
for {
|
||
|
// log.Println(p)
|
||
|
|
||
|
selectStocks := GetStocksByCondition(cday, p)
|
||
|
// log.Println(len(selectStocks))
|
||
|
|
||
|
if len(selectStocks) == 0 {
|
||
|
cday = cday.Add(time.Hour * 24)
|
||
|
if cday.After(GetDate("2022-07-02")) {
|
||
|
cday = GetDate("2017-05-01")
|
||
|
money = 1000000.0
|
||
|
continue RESET
|
||
|
}
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
if len(selectStocks) >= 15 {
|
||
|
selectStocks = selectStocks[3:13]
|
||
|
}
|
||
|
|
||
|
// ShowSelectStocks(selectStocks)
|
||
|
|
||
|
// TODO: 测试 收益
|
||
|
iter := DateStocks.Iterator()
|
||
|
iter.SeekGT(cday.Unix())
|
||
|
if !iter.Valid() {
|
||
|
break
|
||
|
}
|
||
|
|
||
|
for {
|
||
|
var total float64 = 0.0
|
||
|
iter.Next()
|
||
|
|
||
|
if !iter.Valid() {
|
||
|
break ALL_LOOP
|
||
|
}
|
||
|
cstocks := iter.Value() // 当天的股票数据
|
||
|
|
||
|
// 当前股票
|
||
|
var cs *Stock
|
||
|
|
||
|
for _, s := range selectStocks {
|
||
|
itf, ok := cstocks.Get(s.Code)
|
||
|
if ok {
|
||
|
cs = itf
|
||
|
var ClosePrice float64
|
||
|
if cs.ClosingPrice == 0 {
|
||
|
ClosePrice = cs.PreviousClosingPrice
|
||
|
} else {
|
||
|
ClosePrice = cs.ClosingPrice
|
||
|
}
|
||
|
total += (ClosePrice - s.ClosingPrice) / s.ClosingPrice
|
||
|
// log.Printf("%.2f", (cs.ClosingPrice-s.ClosingPrice)/s.ClosingPrice)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
total = total / float64(len(selectStocks))
|
||
|
|
||
|
// log.Printf("%s 总收益: money: %f, 涨跌幅:%.2f%%", cs.Date.Local().Format("2006-01-02"), money+money*total, total*100)
|
||
|
if total >= 0.08 || total <= -0.08 {
|
||
|
|
||
|
for _, s := range selectStocks {
|
||
|
show, ok := cstocks.Get(s.Code) // 当前股票
|
||
|
if ok {
|
||
|
log.Printf("%s %s 买入:%f 当前:%f", s.Date.Local().Format("2006-01-02"), s.Name, s.ClosingPrice, show.ClosingPrice)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
money = money + money*total
|
||
|
cday = cs.Date
|
||
|
log.Printf("最后总财富 1000000 -> money: %f, 涨跌幅: %.2f%%", money, (money-1000000)/1000000*100)
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
log.Printf("最后总财富 本金:1000000 -> money: %f, 涨跌幅: %.2f%%", money, (money-1000000)/1000000*100)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type RangeValue[T float32 | float64 | int | int64 | uint32 | uint64] struct {
|
||
|
Min T
|
||
|
MinLimt T
|
||
|
Max T
|
||
|
MaxLimit T
|
||
|
Step T
|
||
|
}
|
||
|
|
||
|
func (rv *RangeValue[T]) In(v T) bool {
|
||
|
return v >= rv.Min && v <= rv.Max
|
||
|
}
|
||
|
|
||
|
type Policy struct {
|
||
|
Hash hash.Hash
|
||
|
MarketValue *RangeValue[float64]
|
||
|
UpsDownsRatioDays []*RangeValue[float64]
|
||
|
UpsCount *RangeValue[int]
|
||
|
DownsCount *RangeValue[int]
|
||
|
MaxPriceRatio *RangeValue[float64]
|
||
|
MinPriceRatio *RangeValue[float64]
|
||
|
}
|
||
|
|
||
|
func GetStocksByCondition(cday time.Time, policy *Policy) []*Stock {
|
||
|
var stocks []*Stock
|
||
|
|
||
|
// cday := GetDate(CurrentDay)
|
||
|
|
||
|
// log.Println("重新从", cday.Local().Format("2006-01-02"), "策略选股")
|
||
|
|
||
|
iter := DateStocks.Iterator()
|
||
|
|
||
|
// log.Println(iter.SeekLE(cday.Unix()), iter.Valid())
|
||
|
iter.SeekGE(cday.Unix())
|
||
|
if !iter.Valid() {
|
||
|
return nil
|
||
|
}
|
||
|
endStock := iter.Value()
|
||
|
|
||
|
// log.Println(DateStocks.Size(), endStock.Size())
|
||
|
|
||
|
endStock.Traverse(func(s *treelist.Slice[int64, *Stock]) bool {
|
||
|
|
||
|
stock := s.Value
|
||
|
if stock.Name[0] == '*' {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
if len(stock.Extend.UpsDownsRatioDays) < 4 {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
// if !(stock.MarketValue >= 50*亿) {
|
||
|
// return true
|
||
|
// }
|
||
|
|
||
|
if !(policy.MarketValue.In(stock.MarketValue / 亿)) {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
udDays := stock.Extend.UpsDownsRatioDays
|
||
|
// if !(udDays[0].Ratio < -0.02 && udDays[3].Ratio > 0.03) {
|
||
|
// return true
|
||
|
// }
|
||
|
|
||
|
for i, ratio := range policy.UpsDownsRatioDays {
|
||
|
if !ratio.In(udDays[i].Ratio) {
|
||
|
return true
|
||
|
}
|
||
|
if !policy.UpsCount.In(udDays[i].UpsCount) {
|
||
|
return true
|
||
|
}
|
||
|
if !policy.DownsCount.In(udDays[i].DownsCount) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
|
||
|
maxRatio := (stock.Extend.MaxPriceDays - stock.ClosingPrice) / stock.ClosingPrice
|
||
|
if !policy.MaxPriceRatio.In(maxRatio) {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
minRatio := (stock.ClosingPrice - stock.Extend.MinPriceDays) / stock.ClosingPrice
|
||
|
if !policy.MaxPriceRatio.In(minRatio) {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
if stock.ClosingPrice == 0 {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
// log.Println(stock.UpsDownsRatio, s)
|
||
|
|
||
|
stocks = append(stocks, stock)
|
||
|
return true
|
||
|
})
|
||
|
|
||
|
sort.Slice(stocks, func(i, j int) bool {
|
||
|
return stocks[i].UpsDownsRatio < stocks[j].UpsDownsRatio
|
||
|
})
|
||
|
|
||
|
return stocks
|
||
|
}
|