美文网首页
julia分析股市的【春季躁动】(2)——集成多个指标后画图观察

julia分析股市的【春季躁动】(2)——集成多个指标后画图观察

作者: 昵称违法 | 来源:发表于2020-12-30 10:15 被阅读0次

一、前言:

用julia搜集了一些数据,并分析它们,最后显示在一个plot上,便于直观判断。

以【中科曙光】为例,plot由四个部分组成
【1】中科曙光历史上每年春季躁动的涨跌幅统计,统计的区间,用竖线画出来。
【2】历史上每年Q3时,基金持股和较上一季报加减仓信息。
【3】历史上每年中,各个季度的营业总收入
【4】历史上每年中,各个季度的归母净利润

image.png

二、图形解析:

【1】中科曙光自上市以来,一共经过6次春季躁动(2015-2020),其中2016年下跌,其它年份的春季躁动都是上涨,且涨幅最低8%,最高87%,近四年来的春季躁动,都是连续上涨,平均涨幅25%。
【2】中科曙光股价最近处于低点,半年多来的低点。
【3】2020Q3基金持仓站流通市值8.37%,其中基金加仓0.64%
【4】今年的归母净利润预计略高于去年
【5】今年的营业收入预计与去年持平

结论:中科曙光可以纳入观察,春节前出现信号则买入。
风险:关注贸易战、中美关系、科技制裁、军工、内循环需求、进口替代

下图为【鲁北化工】:大家自己分析,我看了一眼,基金突然加仓,财务也比较靓,股价也不高,建议大家自己深挖。


image.png

三、julia画图代码

我用的是julia1.4版本,GR对中文不支持,以前有版本支持,现在还没update,所以改用pyplot

plot支持中文的设置

pyplot对中文支持的设置如下:

using PyCall

py"""
import matplotlib.pyplot as plt
import numpy as np

plt.rcParams['font.sans-serif']=['SimHei'] #👈👈👈用来正常显示中文标签👈👈👈
plt.rcParams['axes.unicode_minus']=False   #正常显示负号
#plt.rcParams["figure.figsize"] = (20,10)  #设置图片的大小
plt.figure(dpi = 300)  #设置分辨率
plt.grid(True)         #添加图表网格线
"""

把多个plot组成一个plot

"""
画图:把四个图画到一个plot里面
"""
function draw_plot(code,idx,path,stocks_dict,fund_df,revenue_profit_df)
    stock_df = stocks_dict[code]
    p_kline = draw_kline(stock_df,info_df,tasks_df,code)

    q_df = @linq fund_df |> where(:代码1 .== code)
    sort!(q_df,:躁动年份)
    p_fund = draw_fund_hoding(q_df)

    q_df = @linq revenue_profit_df |> where(:代码 .== code)
    p_profit = draw_profit(q_df)
    p_revenue = draw_revenue(q_df)

    p_all = plot(p_kline,p_fund,p_profit, p_revenue, layout = (4, 1), legend = false)
    display(p_all)
    savefig("$(path)/$(idx)-$(code).svg")
end

代码


using CSV
using DataFrames
using DataFramesMeta
using Dates
using XLSX
using Statistics
using PyCall

include("common.jl")

#👉👉读取股票信息表👈👈
info_df = DataFrame(XLSX.readtable("data/股票信息.xlsx","Sheet1")...)
info_df[!,"stockID"] = info_df.证券代码 .|> stock -> split(stock,".")[1] |> string
stocks = info_df.证券代码 |> unique
info_df |> display

codes = info_df.证券代码 |> unique .|> stock->split(stock,".")[1] |> string

#👉👉读取开平仓的时间点👈👈
kpc_df = DataFrame(XLSX.readtable("data/年份开平仓日期.xlsx","sheet1")...)
kpc_df |> display

kpc_dict = Dict()
for r in eachrow(kpc_df)
    kpc_dict[r.年份] = (开仓日期 = r.开仓日期,平仓日期 = r.平仓日期)
end
kpc_dict |> display

#👉👉读取股票的k线信息,装入dict中👈👈
stocks_dict = Dict()
for stock in codes
    println(stock)
    kind = "股票"
    stock = split(stock,".")[1] |> string
    if length(stock) < 6 #有港股代码,需要排除
        continue #for
    end

    kline_directory = "D:/juliaWorkSpace/k线"  #k线位置
    df = read_kline(kind, stock, kline_directory)

    #填补空值 ismissing的值,用上一个单元格的值来填补
    for idx = 1:size(df)[1]
        if idx > 1
            for col in names(df)
                if ismissing(df[idx, col])
                    df[idx, col] = df[idx-1, col]
                end
            end
        end
    end

    stocks_dict[stock] = df
end

stocks_dict

"""
获取收盘价
df:k线数据表
"""
function get_close(df,date)
    q_df = @linq df |> where(:day .== date)
    if size(q_df,1) >0
        q_df[1,"close"]
    else
        NaN
    end
end

#get_close(stock_df,Date("2010-01-11"))

using Plots
#gr()
pyplot()
Plots.GRBackend()

py"""
import matplotlib.pyplot as plt
import numpy as np

plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False   #正常显示负号
#plt.rcParams["figure.figsize"] = (20,10)  #设置图片的大小
plt.figure(dpi = 300)  #设置分辨率
plt.grid(True)         #添加图表网格线
"""

"""
获取一只股票的信息
df:股票信息表
code:股票代码【尽量不要加市场后缀】

返回值:(证券简称 = name,所属规模风格类型 = ..,行业 = ..,细分行业 = ..)

get_stock_info(info_df,"600352").证券简称
"""
function get_stock_info(df,code)
    q_df = @linq info_df |> where(occursin.(Ref(code),:证券代码))
    if size(q_df,1) > 0
        name = q_df[1,"证券简称"]
        style = q_df[1,"所属规模风格类型"]
        industry = q_df[1,"行业"]
        sub_industry = q_df[1,"细分行业"]
    else
        name = ""
        style = ""
        industry = ""
        sub_industry = ""
    end
    return(证券简称 = name,所属规模风格类型 = style,行业 = industry,细分行业 = sub_industry)
end

"""
未达到指定的长度,字符串在尾部用空值补足
str:给定的字符串
len:要是之达到的长度

fill_string("-5.64",8)|>println
"""
function fill_string(str,len)
    if length(str) > len
        throw("$(str)的长度超过了$(len)")
    end

    fill_num = len - length(str)
    final_str = str
    for i in 1:fill_num
        final_str = string(final_str," ")
    end
    final_str
end #end fill_string


"""
获取股票躁动的历年信息
df:已经统计完成的春季躁动表
code:股票代码
"""
function get_stock_tj_info(df, code)
    q_df = @linq df |> where(occursin.(Ref(code), :证券代码))
    if size(q_df, 1) > 0
        最近x年连胜 = q_df[1,:最近x年连胜]
        最近连胜平均涨跌幅 = q_df[1,:最近连胜平均涨跌幅]
        期间x年连胜 = q_df[1,:期间x年连胜]
        期间连胜平均涨跌幅 = q_df[1,:期间连胜平均涨跌幅]
        y2011 = q_df[1,:y2011]
        y2012 = q_df[1,:y2012]
        y2013 = q_df[1,:y2013]
        y2014 = q_df[1,:y2014]
        y2015 = q_df[1,:y2015]
        y2016 = q_df[1,:y2016]
        y2017 = q_df[1,:y2017]
        y2018 = q_df[1,:y2018]
        y2019 = q_df[1,:y2019]
        y2020 = q_df[1,:y2020]
    else
    end
    return(
    最近x年连胜 = 最近x年连胜,
    最近连胜平均涨跌幅 = 最近连胜平均涨跌幅,
    期间x年连胜 = 期间x年连胜,
    期间连胜平均涨跌幅 = 期间连胜平均涨跌幅,
    y2011 = y2011,
    y2012 = y2012,
    y2013 = y2013,
    y2014 = y2014,
    y2015 = y2015,
    y2016 = y2016,
    y2017 = y2017,
    y2018 = y2018,
    y2019 = y2019,
    y2020 = y2020
    )
end #function get_stock_tj_info

"""
生成各年涨跌幅的信息
res = get_stock_tj_info(tasks_df,"600352")
get_year_gain_str(res) |>println
"""
function get_year_gain_str(res)
    year_gain_str  = ""
    年份 = ""
    涨跌 = ""
    for y in 2011:2020
        value = res[Symbol("y$(y)")]
        if typeof(value) == String
            value = parse(Float64,value)
        end
        value = isnan(value) ? 0.0 : value  #有NaN的值
        value = round(value,digits = 2)
        年份 = string(年份,fill_string("$(y)",8),"|")
        涨跌 = string(涨跌,fill_string("$(value)",8),"|")
    end

    year_gain_str = string(year_gain_str,"\n","年份  :|",年份)
    year_gain_str = string(year_gain_str,"\n","涨跌  :|",涨跌)
end #function get_year_gain_str

"""
春季躁动画图分析
"""
function draw_kline(df, info_df, tasks_df, code)
    #股票简要信息
    info = get_stock_info(info_df, code)
    title_text = "【$(code)】 【$(info.证券简称)】 【$(info.所属规模风格类型)】 【$(info.行业)】 【$(info.细分行业)】"

    res = get_stock_tj_info(tasks_df, code)
    最近x年连胜 = res.最近x年连胜
    最近连胜平均涨跌幅 = res.最近连胜平均涨跌幅
    title_text = string(title_text, "\n最近x年连胜:$(最近x年连胜),平均涨跌幅:$(最近连胜平均涨跌幅)")
    期间x年连胜 = res.期间x年连胜
    期间连胜平均涨跌幅 = res.期间连胜平均涨跌幅
    title_text = string(title_text, "\n期间x年连胜:$(期间x年连胜),平均涨跌幅:$(期间连胜平均涨跌幅)")


    res = get_stock_tj_info(tasks_df, code)
    year_gains = get_year_gain_str(res)
    title_text = string(title_text, "\n", year_gains)

    #画收盘价的线
    x = df.day
    y = df.close
    p1 = plot(
        x,
        y,
        w = 1,
        title = title_text,
        size = (3000, 1500),
        legend = false,
        bg = RGB(0.2, 0.2, 0.2),
    )

    #画各个春季躁动的起始和结束分隔线
    for year = 2011:2020
        begin_date = kpc_dict[year].开仓日期
        end_date = kpc_dict[year].平仓日期

        if df.day[1] <= begin_date
            x1 = [begin_date, begin_date]    #x轴刻度值
            close1 = get_close(df, begin_date)
            y1 = [0, close1]
            plot!(x1, y1, w = 1, color = :green)

            x2 = [end_date, end_date]
            close2 = get_close(df, end_date)
            y2 = [0, close2]
            plot!(x2, y2, w = 1, color = :red)
        end
    end

    #画每年第一个交易日的一个竖线,用于分隔各年的k线
    for year = 2011:2020
        start_date = "$(year)-01-01" |> Date
        end_date = "$(year)-12-31" |> Date
        q_df = @linq df |> where(start_date .<= :day .<= end_date)
        if size(q_df, 1) > 0
            date1 = q_df[1, "day"]
            x3 = [date1, date1]
            close3 = get_close(df, date1)
            y3 = [0, close3]
            plot!(x3, y3, w = 1, color = :yellow)

        end
    end
    #savefig(p1, "data/k线图/$(idx)_$(code).svg")
    #display(p1)
    return p1
end

#读取基金持仓的信息
fund_df = CSV.read("data\\主流程5 增加基金持股信息到地4步的选股结果\\输入数据\\基金持仓和加仓信息.csv")
fund_df |> names
fund_df[!,"代码1"] = fund_df.代码 .|> code->split(code,".")[1] |>string

"""
画某股票被基金持股的年度对比图
"""
function draw_fund_hoding(q_df)
    x = [y for y in 2010:2021]    #年份
    y = begin                     #年份 - 持股占流通股比(%)
        ary = []
        for year in x
            tmp_df = @linq q_df |> where(:躁动年份 .== year )
            if size(tmp_df,1) > 0
                push!(ary,tmp_df[1,"持股占流通股比(%)"])
            else
                push!(ary,0.0)
            end
        end
        ary
    end

    holding2020q3,chg2020q3 = begin
        df2020q3 = @linq q_df |> where(:躁动年份 .== 2021)
        if size(df2020q3,1) > 0
            (df2020q3[1,"持股占流通股比(%)"],df2020q3[1,"加减仓占流通股比(%)"])
        else
            (0.0,0.0)
        end
    end

    title_text = "各年Q3公告时,基金持仓占流通市值百分比"
    holding_ratio = holding2020q3
    chg_ratio = chg2020q3
    title_text = string(title_text,"\n 2020 Q3 持仓占比:$(holding_ratio),相较2020 Q2持仓变化的股份占流通市值百分比:$(chg_ratio)")

    p1 = plot(
        x,
        y,
        w = 1,
        title = title_text,
        #color = colors,
        seriestype = bar, # :scatter,
        size = (3000, 1500),
        legend = false,
        bg = RGB(0.2, 0.2, 0.2),
    )
    #savefig("data/p1.svg")
    #display(p1)
    return p1
end

q_df = @linq fund_df |> where(:代码1 .== "002371")
sort!(q_df,:躁动年份)
p2 = draw_fund_hoding(q_df)


"""
画出各个季度的财报营业总收入
输入:q_df 包含列名
x = q_df.report_date                 财报日期
y = q_df.total_operating_revenue     报告的净利润

不用的季度采用不同的颜色
"""
function draw_revenue(q_df)

    x = q_df.report_date
    y = q_df.total_operating_revenue |> ary -> Missings.replace(ary,0.0) |> collect #替换missing值

    title_text = "营业总收入,每个季度累加\n hongse = q1,橙色 = q2,黄色 = q3,绿色 = q4"

    colors = []
    for d in q_df.report_date
        m = d |> month
        if m == 3
            push!(colors, "red")
        elseif m == 6
            push!(colors, "orange")
        elseif m == 9
            push!(colors, "yellow")
        elseif m == 12
            push!(colors, "green")   #第四季度变成绿色,用于区分各年的财报
        else

        end
    end

    p1 = plot(
        x,
        y,
        w = 1,
        title = title_text,
        color = colors,
        seriestype = bar, # :scatter,
        size = (3000, 1500),
        legend = false,
        bg = RGB(0.2, 0.2, 0.2),
    )

    #display(p1)
    return p1
end


"""
画出各个季度的财报归母净利润
输入:q_df 包含列名
x = q_df.report_date                   财报日期
y = q_df.np_parent_company_owners      报告的净利润

不用的季度采用不同的颜色
"""
function draw_profit(q_df)
    x = q_df.report_date
    y = q_df.np_parent_company_owners

    title_text = "归母净利润,每个季度累加\n hongse = q1,橙色 = q2,黄色 = q3,绿色 = q4"

    colors = []
    for d in q_df.report_date
        m = d |> month
        if m == 3
            push!(colors, "red")
        elseif m == 6
            push!(colors, "orange")
        elseif m == 9
            push!(colors, "yellow")
        elseif m == 12
            push!(colors, "green")   #第四季度变成绿色,用于区分各年的财报
        else

        end
    end

    p1 = plot(
        x,
        y,
        w = 1,
        title = title_text,
        color = colors,
        seriestype = bar, # :scatter,
        size = (3000, 1500),
        legend = false,
        bg = RGB(0.2, 0.2, 0.2),
    )

    #display(p1)
    return p1
end


#需要打印的k线
tasks_df = DataFrame(XLSX.readtable("data/需要打印k线的春季躁动列表.xlsx","Sheet1")...)
sort!(tasks_df,[:最近x年连胜,:最近连胜平均涨跌幅],rev = true)
task_codes = tasks_df.证券代码 .|> code -> split(code,".")[1] |> string

#读取《营收和净利指标.csv》表
revenue_profit_df = CSV.read("data/主流程-7-增加各年各季度的营收和归母净利润/输入数据/营收和净利指标.csv")
revenue_profit_df[!, "代码"] = revenue_profit_df.code .|> code -> split(code, ".")[1] |> string

#读取基金持仓的信息
fund_df = CSV.read("data\\主流程5 增加基金持股信息到地4步的选股结果\\输入数据\\基金持仓和加仓信息.csv")
fund_df[!,"代码1"] = fund_df.代码 .|> code->split(code,".")[1] |>string

"""
画图:把四个图画到一个plot里面
"""
function draw_plot(code,idx,path,stocks_dict,fund_df,revenue_profit_df)
    stock_df = stocks_dict[code]
    p_kline = draw_kline(stock_df,info_df,tasks_df,code)

    q_df = @linq fund_df |> where(:代码1 .== code)
    sort!(q_df,:躁动年份)
    p_fund = draw_fund_hoding(q_df)

    q_df = @linq revenue_profit_df |> where(:代码 .== code)
    p_profit = draw_profit(q_df)
    p_revenue = draw_revenue(q_df)

    p_all = plot(p_kline,p_fund,p_profit, p_revenue, layout = (4, 1), legend = false)
    display(p_all)
    savefig("$(path)/$(idx)-$(code).svg")
end

code = "600352"
idx = 1
path = "data/k线图"
draw_plot(code,idx,path,stocks_dict,fund_df,revenue_profit_df)

tasks_df = DataFrame(XLSX.readtable("data/需要打印k线的春季躁动列表.xlsx","Sheet1")...)
sort!(tasks_df,[:最近x年连胜,:最近连胜平均涨跌幅],rev = true)
task_codes = tasks_df.证券代码 .|> code -> split(code,".")[1] |> string

code = "600603"
idx = 1
path = "data/k线图"
draw_plot(code,idx,path,stocks_dict,fund_df,revenue_profit_df)

codes = task_codes[1:434]
for (idx,code) in zip(1:length(codes),codes)
    println(code)
    draw_plot(code,idx,path,stocks_dict,fund_df,revenue_profit_df)
    idx += 1
end


"""
todo:
(*)增加Q3时基金持股信息:【持股家数】,【占流通比】
(*)增加年份的notation
(*)增加财务信息,各年的各季度的【营收】和【利润】
(*)更新k线数据,更新到最新的k线
"""


#读取判断条件,进行过滤
filter_df_finaces = CSV.read("data/单独流程 - 画k线观察各个躁动年份/输入数据/2020年三个季度净利润同比增长率为正.csv")
filter_df_fund_hold = CSV.read("data/单独流程 - 画k线观察各个躁动年份/输入数据/基金持仓筛选后的股票.csv")

filter_df_fund_hold |> names |> println

codes1 = filter_df_fund_hold.代码 |> unique |> Set .|> item->split(item,".")[1] |> string
codes2 = filter_df_finaces.代码 |> unique |> Set .|> item->split(item,".")[1] |> string

intersect(codes1,codes2)


#打印k线
tasks_df = DataFrame(CSV.read("data/单独流程 - 画k线观察各个躁动年份/截至当前-已经连续X年取胜且满足[财报]和[基金]持股的条件.csv"))
sort!(tasks_df,[:最近x年连胜,:最近连胜平均涨跌幅],rev = true)
task_codes = tasks_df.证券代码 .|> code -> split(code,".")[1] |> string

code = "600519"
stock_df = stocks_dict[code]
draw(stock_df,info_df,tasks_df,code,1)

codes = task_codes
for (idx,task_code) in zip(1:length(codes),codes)
    println(task_code)
    stock_df = stocks_dict[task_code]
    draw(stock_df, info_df, tasks_df, task_code,idx)
    idx += 1
end

相关文章

网友评论

      本文标题:julia分析股市的【春季躁动】(2)——集成多个指标后画图观察

      本文链接:https://www.haomeiwen.com/subject/wqicoktx.html