AnyMath 文档
Notebook

股票报价的提取和初级分析

导言

本文介绍了使用YFinance库提取和初步分析股票市场报价,该库提供了从Yahoo Finance financial门户访问数据的程序化访问。

*雅虎财经**是最大的公共金融门户网站之一,积累了来自许多全球平台(纳斯达克,纽约证券交易所,美国运通,ARCA,BATS)的股票,基金,货币和商品资产的交换信息。 图书馆 YFinance 它允许您直接从代码访问这些数据,这使其成为教育和分析任务的便捷工具。

在这个例子中,让我们看看苹果公司的股票报价。 (AAPL)为期一年,以一个交易日为增量。 基于它们,我们将计算和可视化一些关键特征。:

*价格动态–收盘价随时间变化的图表,让您可以看到工具的整体趋势,增长和下跌时期以及波动幅度。
*交易量-在间隔期间买入和卖出的股票数量。 该指标反映了市场参与者的活动和工具的流动性。
*盈利能力是在一个区间内的相对价格变化;它显示了投资者在一个步骤中获得或损失了多少投资金额。
*波动率是衡量回报变异性的指标,通常以标准差来衡量。 波动性越高,价格波动越大,工具的风险就越高。
*累积盈利能力是从周期开始到当前时刻持有股票的最终结果;它允许您在同一图表上比较多个工具。
*回撤-显示当前价格低于其历史最高值多少,并表征下跌的深度和投资者的最大损失。

此外,我们将比较几家大型科技公司(AAPL,MSFT,NVDA,AMZN)的累积盈利能力,这将使我们能够评估所选工具的相对有效性。

这项工作的目的是展示一只股票的全周期定量分析:从从外部来源获得报价到计算和可视化表征其盈利能力、风险和投资吸引力的指标。

加入图书馆

对于这项工作,我们将需要以下库:

  • YFinance -从雅虎财经获取股票数据;
  • DataFrames -使用表格数据;
  • Statistics -使用表格数据;
  • Dates -与日期和时间的工作;
  • Colors -在可视化中使用颜色。
In [ ]:
for lib in ["YFinance", "DataFrames", "Statistics", "Dates", "Colors"]
    try
        eval(Meta.parse("using $lib"))
    catch ex
        import Pkg
        Pkg.add(lib)
        eval(Meta.parse("using $lib"))
    end
end

选择交易所并显示股票列表

图书馆 YFinance 允许您从以下交易所提取股票报价数据:

*美国运通-美国证券交易所
*ARCA-群岛交易所
*蝙蝠-更好的替代交易系统交换
*纳斯达克-全国证券交易商协会自动报价
*NYSE–纽约证券交易所

对于我们的研究,我们将选择纳斯达克证券交易所,并显示在此交易所交易的股票名称的简短列表。 您可以使用以下命令显示完整列表 print(акции).

In [ ]:
акции = get_all_symbols("NASDAQ")
display(акции)
# 印刷(推广)
5622-element Vector{String}:
 "AAAP"
 "AACG"
 "AACI"
 "AACIU"
 "AACIW"
 "AACO"
 "AACOU"
 "AACOW"
 "AACP"
 "AACPR"
 "AACPU"
 "AACPW"
 "AADR"
 ⋮
 "ZSQR"
 "ZSTK"
 "ZTEN"
 "ZTG"
 "ZTOP"
 "ZTRE"
 "ZTWO"
 "ZUMZ"
 "ZURA"
 "ZVRA"
 "ZYBT"
 "ZYME"

股票、期间及间隔的选择

让我们选择一个周期,一个区间,以及我们将调查其股票价格的公司。

期间 range –这是从当前时刻(本示例的发布时刻或脚本启动时刻)到过去的一段时间,在此期间加载可用的交换数据。 周期设置为整数和时间单位指定。 周期的终点由最新的可用数据确定,通常对应于最后完成的交易间隔。 例如:最近7天、3个月或2年。

间隔时间 interval –这是在所选期间内呈现数据的步骤:例如,1分钟,1小时或1天。

股价在每个选定区间收盘时是固定的. 例如,间隔为1天,这是交易日的收盘价,间隔为5分钟,则是每个5分钟间隔的收盘价。

期设置如下:

  • m -分钟: 30m -30分钟;

  • d -天数: 7d -7天;

  • mo -月: 3mo -3个月;

  • y -年: 2y –2岁;

  • ytd –自今年年初以来;

  • max -最大可用期限。

间隔只能从固定列表中选择。: 1m, 2m, 5m, 15m, 30m, 60m, 90m, 1h, 1d, 5d, 1wk, 1mo, 3mo. 但是,期间更灵活:例如,期间 7m 这意味着7分钟,因为对于 range 您可以指定任意分钟数(天、月、年)。

让我们选择苹果公司的股票。 (AAPL)为研究对象。

In [ ]:
акция = "AAPL"
период = "1y"
интервал = "1d"
println("库存: ", акция, "\nПериод: ", период, "\nИнтервал: ", интервал)
Акция: AAPL
Период: 1y
Интервал: 1d

提取源数据

我们将根据所选的股票、周期和间隔提取股票报价的值。 日期和时间数据按照UTC+0时区显示。

In [ ]:
данные = get_prices(акция, range = период, interval = интервал)
println("Данные извлечены\nКоличество наблюдений: ", length(данные["close"]))
Данные извлечены
Количество наблюдений: 251

将数据转换为数据框

将接收到的数据转换为DataFrame,并将日期和时间数据转换为UTC+3。 日期和时间现在将对应于莫斯科时区。

In [ ]:
df = DataFrame(данные)
df.timestamp = df.timestamp .+ Hour(3)
display(df)
251×8 DataFrame
226 rows omitted
Rowtickertimestampopenhighlowcloseadjclosevol
StringDateTimeFloat64Float64Float64Float64Float64Float64
1AAPL2025-10-09T16:30:00256.861257.05252.208254.04253.1053.8181e7
2AAPL2025-10-10T16:30:00254.002255.436243.102245.27244.3676.17709e7
3AAPL2025-10-13T16:30:00248.462248.771244.656247.66246.7493.80025e7
4AAPL2025-10-14T16:30:00245.692247.934243.799247.77246.8583.53474e7
5AAPL2025-10-15T16:30:00248.572250.893246.559249.34248.4223.37689e7
6AAPL2025-10-16T16:30:00247.336248.123244.228247.45246.5393.96306e7
7AAPL2025-10-17T16:30:00247.107252.447246.36252.29251.3614.89661e7
8AAPL2025-10-20T16:30:00254.948263.407254.689262.24261.2759.015e7
9AAPL2025-10-21T16:30:00260.916264.314260.866262.77261.8034.6524e7
10AAPL2025-10-22T16:30:00261.683261.883254.49258.45257.4994.48496e7
11AAPL2025-10-23T16:30:00258.983259.661257.06259.58258.6253.26343e7
12AAPL2025-10-24T16:30:00260.229263.158258.226262.82261.8533.81129e7
13AAPL2025-10-27T16:30:00263.905268.13263.676268.81267.8214.4723e7
⋮⋮⋮⋮⋮⋮⋮⋮⋮
240AAPL2026-09-23T16:30:00341.08341.8335.5337.02337.023.16588e7
241AAPL2026-09-24T16:30:00336.72338.91334.3335.92335.922.47331e7
242AAPL2026-09-25T16:30:00336.04341.67334.53341.07341.073.00025e7
243AAPL2026-09-28T16:30:00340.37342.99338.04338.4338.43.28208e7
244AAPL2026-09-29T16:30:00336.97337.09328.7329.4329.43.8478e7
245AAPL2026-09-30T16:30:00330.8339.5330.14333.02333.024.99886e7
246AAPL2026-10-01T16:30:00330.0332.48325.81330.32330.323.63063e7
247AAPL2026-10-02T16:30:00333.26334.54330.61333.69333.693.32786e7
248AAPL2026-10-05T16:30:00332.82336.21331.65332.89332.893.44009e7
249AAPL2026-10-06T16:30:00332.28334.38330.62333.63333.633.0449e7
250AAPL2026-10-07T16:30:00336.96338.67332.78336.67336.673.41479e7
251AAPL2026-10-08T16:30:00336.82341.57335.9340.42340.423.52799e7

主要股票特征

让我们展示所研究公司股票的主要股票特征。

In [ ]:
println("库存: ", акция)
println("期的开始: ", first(df.timestamp), " UTC+3")
println("期末:  ", last(df.timestamp), " UTC+3")
println("间隔数: ", nrow(df))
println("\nНачальная цена: ", round(first(df.close), digits=2), " \$")
println("最终价格:  ", round(last(df.close), digits=2), " \$")
println("最低限额:         ", round(minimum(df.close), digits=2), " \$")
println("最大值:        ", round(maximum(df.close), digits=2), " \$")
Акция: AAPL
Начало периода: 2025-10-09T16:30:00 UTC+3
Конец периода:  2026-10-08T16:30:00 UTC+3
Количество интервалов: 251

Начальная цена: 254.04 $
Конечная цена:  340.42 $
Минимум:         245.27 $
Максимум:        341.07 $

价格动态

让我们绘制选定时期的股票价格动态。

In [ ]:
plot(
    df.timestamp,
    df.close,
    xlabel = "日期及时间",
    ylabel = "Цена, \$",
    title  = "$акция – динамика цены",
    label  = "价格;价格",
    linewidth = 2.2,
    legend = false,
    hover = ["Дата и время: $(Dates.format(df.timestamp[i], "dd.mm.yyyy HH:MM")) UTC+3 | Цена: $(round(df.close[i], digits=2)) \$" 
    for i in 1:length(df.close)],
    linecolor = RGB(0/255, 198/255, 201/255))
Out[0]:

交易量

让我们根据选定的周期和间隔绘制交易量图表。

In [ ]:
plot(
    df.timestamp,
    df.vol,
    xlabel = "日期及时间",
    ylabel = "股份数目",
    title = "$акция – объём торгов",
    label = false,
    linewidth = 2.2,
    legend = false,
    hover = ["Дата и время: $(Dates.format(df.timestamp[i], "dd.mm.yyyy HH:MM")) UTC+3 | " * "$(round(Int, df.vol[i])) акций"
    for i in eachindex(df.vol)], linecolor = RGB(1, 117/255, 56/255))
Out[0]:

盈利能力

区间收益率使用公式计算:

哪里:

  • -观察的序列号;
  • -计算涨幅的相对价格;
  • -价格是下一个观察的收盘价。

计算区间返回并将计算值放在新列中。

In [ ]:
df.Доходность = [missing; diff(df.close) ./ df.close[1:end-1]]
display(df)
251×9 DataFrame
226 rows omitted
RowtickertimestampopenhighlowcloseadjclosevolДоходность
StringDateTimeFloat64Float64Float64Float64Float64Float64Float64?
1AAPL2025-10-09T16:30:00256.861257.05252.208254.04253.1053.8181e7missing
2AAPL2025-10-10T16:30:00254.002255.436243.102245.27244.3676.17709e7-0.0345221
3AAPL2025-10-13T16:30:00248.462248.771244.656247.66246.7493.80025e70.00974436
4AAPL2025-10-14T16:30:00245.692247.934243.799247.77246.8583.53474e70.00044416
5AAPL2025-10-15T16:30:00248.572250.893246.559249.34248.4223.37689e70.00633649
6AAPL2025-10-16T16:30:00247.336248.123244.228247.45246.5393.96306e7-0.00758001
7AAPL2025-10-17T16:30:00247.107252.447246.36252.29251.3614.89661e70.0195595
8AAPL2025-10-20T16:30:00254.948263.407254.689262.24261.2759.015e70.0394387
9AAPL2025-10-21T16:30:00260.916264.314260.866262.77261.8034.6524e70.00202104
10AAPL2025-10-22T16:30:00261.683261.883254.49258.45257.4994.48496e7-0.0164401
11AAPL2025-10-23T16:30:00258.983259.661257.06259.58258.6253.26343e70.00437212
12AAPL2025-10-24T16:30:00260.229263.158258.226262.82261.8533.81129e70.0124818
13AAPL2025-10-27T16:30:00263.905268.13263.676268.81267.8214.4723e70.0227912
⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮
240AAPL2026-09-23T16:30:00341.08341.8335.5337.02337.023.16588e7-0.00803535
241AAPL2026-09-24T16:30:00336.72338.91334.3335.92335.922.47331e7-0.00326383
242AAPL2026-09-25T16:30:00336.04341.67334.53341.07341.073.00025e70.015331
243AAPL2026-09-28T16:30:00340.37342.99338.04338.4338.43.28208e7-0.00782834
244AAPL2026-09-29T16:30:00336.97337.09328.7329.4329.43.8478e7-0.0265957
245AAPL2026-09-30T16:30:00330.8339.5330.14333.02333.024.99886e70.0109897
246AAPL2026-10-01T16:30:00330.0332.48325.81330.32330.323.63063e7-0.00810757
247AAPL2026-10-02T16:30:00333.26334.54330.61333.69333.693.32786e70.0102022
248AAPL2026-10-05T16:30:00332.82336.21331.65332.89332.893.44009e7-0.0023974
249AAPL2026-10-06T16:30:00332.28334.38330.62333.63333.633.0449e70.00222293
250AAPL2026-10-07T16:30:00336.96338.67332.78336.67336.673.41479e70.00911192
251AAPL2026-10-08T16:30:00336.82341.57335.9340.42340.423.52799e70.0111385

计算回报区间标准差上的平均回报.

In [ ]:
доходности = skipmissing(df.Доходность)
println("平均间隔盈利能力: ", round(mean(доходности) * 100, digits=3), "%")
println("标准偏差: ", round(std(доходности) * 100, digits=3), "%")
Средняя интервальная доходность: 0.129%
Стандартное отклонение: 1.557%

让我们建立一个收益率图。

In [ ]:
plot(
    df.timestamp,
    df.Доходность .* 100,
    xlabel = "日期及时间",
    ylabel = "盈利能力, %",
    title = "$акция – интервальные доходности",
    label = false,
    linewidth = 2,
    legend = false,
    hover = ["Дата и время: $(Dates.format(df.timestamp[i], "dd.mm.yyyy HH:MM")) UTC+3 | Доходность: $(100*round(df.Доходность[i], digits=5))%" 
    for i in 1:length(df.Доходность)],
    linecolor = RGB(221/255, 128/255, 201/204) )
hline!([0])
Out[0]:

让我们构建选定区间收益率分布的直方图。

In [ ]:
histogram(
    collect(доходности) .* 100,
    bins = 40,
    xlabel = "盈利能力, %",
    ylabel = "数量",
    title = "$акция – распределение интервальных доходностей",
    label = false,
    fillcolor = RGB(0/255, 198/255, 201/255) )
Out[0]:

波动性

让我们通过指定区间数来定义波动周期。

In [ ]:
период_волатильности = 20
Out[0]:
20

滚动波动率计算为固定长度滑动窗口中回报的标准偏差。 让我们绘制所选期间的移动波动率图表。

In [ ]:
function скользящая_волатильность(x, окно)
    [std(x[i-окно+1:i])
        for i in окно:length(x)]
end

волатильность = скользящая_волатильность(collect(доходности), период_волатильности)

plot(
    df.timestamp[21:end],
    волатильность .* 100,
    xlabel = "日期及时间",
    ylabel = "波动性, %",
    title = "$акция – волатильность за период",
    label = false,
    linewidth = 2,
    legend = false,
    hover = ["Дата и время: $(Dates.format(df.timestamp[i+период_волатильности], "dd.mm.yyyy HH:MM")) UTC+3 | Волатильность: $(round(100*волатильность[i], digits=4))%" 
    for i in 1:length(волатильность)],
    linecolor = RGB(148/255, 0/255, 211/255) )
Out[0]:

累积盈利能力

累积回报计算为所有区间的增长乘数的乘积。:

哪里:

  • -计算累积盈利能力的区间的顺序编号。

  • -间隔盈利能力 -嗯

    让我们建立一个累积盈利能力的图表。

In [ ]:
накопленная_доходность = cumprod(1 .+ collect(доходности))

plot(
    df.timestamp[2:end],
    (накопленная_доходность .- 1) .* 100,
    xlabel = "日期及时间",
    ylabel = "盈利能力, %",
    title = "$акция – накопленная доходность",
    label = false,
    linewidth = 2,
    legend = false,
    hover = ["Дата и время: $(Dates.format(df.timestamp[i], "dd.mm.yyyy HH:MM")) UTC+3 | Доходность: $(round(100*(накопленная_доходность[i] - 1), digits=3))%" 
    for i in 1:length(накопленная_доходность)],
    linecolor = RGB(245/255, 64/255, 33/255) )


hline!([0], label = "开始")
Out[0]:

缩编

回撤显示当前价格低于迄今为止达到的历史最高值多少。:

哪里:

  • -观察的序列号;

  • -收盘价t;

  • -期间开始至该期间的历史最高价格t包括在内: ,在哪里 -遍历所有值的索引 以前 .

In [ ]:
цены = df.close
просадка = цены ./ accumulate(max, цены) .- 1
println("最大回撤: ", round(minimum(просадка) * 100, digits=2), "%")
Максимальная просадка: -13.82%

让我们为所选期间构建一个回撤图。

In [ ]:
plot(
    df.timestamp,
    просадка .* 100,
    xlabel = "日期及时间",
    ylabel = "缩编, %",
    title = "$акция – просадка за период",
    label = false,
    linewidth = 2,
    legend = false,
    hover = ["Дата и время: $(Dates.format(df.timestamp[i], "dd.mm.yyyy HH:MM")) UTC+3 | Просадка: $(100*round(просадка[i], digits=4))%" 
    for i in 1:length(просадка)],
    linecolor = RGB(48/255, 98/255, 107/255) )
hline!([0], label = "")
Out[0]:

股份摘要特征

让我们展示所选公司股票的最终特征。

In [ ]:
итог = DataFrame(
    Показатель = [
        "Начальная цена",
        "Конечная цена",
        "Минимальная цена",
        "Максимальная цена",
        "Доходность за период",
        "Средняя интервальная доходность",
        "Волатильность доходности",
        "Максимальная просадка"],
    Значение = [
        first(df.close),
        last(df.close),
        minimum(df.close),
        maximum(df.close),
        (last(df.close) / first(df.close) - 1) * 100,
        mean(доходности) * 100,
        std(доходности) * 100,
        minimum(просадка) * 100])

display(итог)
8×2 DataFrame
RowПоказательЗначение
StringFloat64
1Начальная цена254.04
2Конечная цена340.42
3Минимальная цена245.27
4Максимальная цена341.07
5Доходность за период34.0025
6Средняя интервальная доходность0.129267
7Волатильность доходности1.55665
8Максимальная просадка-13.823

与其他股票比较

让我们从AAPL,MSFT,NVDA,AMZN中提取股票报价;并绘制其累积回报的比较图。

In [ ]:
акции = ["AAPL", "MSFT", "NVDA", "AMZN"]
данные_акций = Dict()

for акция in акции
    данные_акций[акция] = get_prices(акция, range = период, interval = интервал)
end

график = plot(xlabel = "日期及时间", ylabel = "累积盈利能力, %",
title = "股票比较", legend = :topleft)

for акция in акции
    данные_текущие = данные_акций[акция]
    даты = данные_текущие["timestamp"]
    цены = данные_текущие["close"]
    доходность = (цены ./ first(цены) .- 1) .* 100
    plot!(график, даты, доходность, label = акция, linewidth = 2, 
    hover = ["Дата и время: $(Dates.format(даты[i], "dd.mm.yyyy HH:MM")) UTC+3 | Доходность: $(round(доходность[i], digits=2))%"
    for i in 1:length(доходность)],)
end

hline!( график, [0], label = "", linestyle = :dash )
display(график)

结论

在这个例子中,基于从库中获得的Yahoo Finance数据执行定量股票分析的整个周期。 YFinance. 构建了价格动态,交易量,区间盈利能力,其分布,滚动波动,累积盈利能力和回撤的图表。 计算最终的特征,包括期间的盈利能力,平均间隔盈利能力,波动性和最大回撤。 此外,还比较了不同公司股票之间的累积回报.

工作成果在各个领域具有实用价值,例如:

*in投资分析-评估工具的盈利能力和风险,并与其类似物进行比较;
in**投资组合管理–-进行风险控制和决策,使投资组合的结构达到给定的目标资产比率;
*在研究中,该方法很容易转移到其他股票,期间和间隔。

由此产生的股票报价可以成为更深入的财务分析的源数据。 您可以选择其他促销、期间和间隔以进行进一步研究。 因此,本示例中实施的一组方法使我们能够对金融工具的行为得出有意义的结论,并作为更严肃研究的方便起点。