<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Investment on 格物堂</title><link>https://gewutang.cn/categories/investment/</link><description>Recent content in Investment on 格物堂</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Tue, 23 Dec 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://gewutang.cn/categories/investment/index.xml" rel="self" type="application/rss+xml"/><item><title>全天候动量ETF策略</title><link>https://gewutang.cn/2025/12/23/all-weather-momentum/</link><pubDate>Tue, 23 Dec 2025 00:00:00 +0000</pubDate><guid>https://gewutang.cn/2025/12/23/all-weather-momentum/</guid><description>&#10;&#10;&#10;&lt;pre&gt;&lt;code&gt;## 正在从Yahoo Finance获取数据...&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;513100.SS&amp;quot; &amp;quot;510300.SS&amp;quot; &amp;quot;518880.SS&amp;quot;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# 2. 计算指标：动量、波动率、调整动量&#10;calculate_metrics &amp;lt;- function(price_series, window = 20) {&#10; # 计算日收益率&#10; returns &amp;lt;- dailyReturn(price_series, type = &amp;quot;arithmetic&amp;quot;)&#10; colnames(returns) &amp;lt;- &amp;quot;Return&amp;quot;&#10; &#10; # 计算20日平均收益率（动量）&#10; momentum &amp;lt;- rollapply(returns, width = window, FUN = mean, align = &amp;quot;right&amp;quot;, fill = NA)&#10; colnames(momentum) &amp;lt;- &amp;quot;Momentum&amp;quot;&#10; &#10; # 计算20日收益率方差（波动率）&#10; volatility &amp;lt;- rollapply(returns, width = window, FUN = var, align = &amp;quot;right&amp;quot;, fill = NA)&#10; colnames(volatility) &amp;lt;- &amp;quot;Volatility&amp;quot;&#10; &#10; # 计算调整动量（动量/波动率）&#10; # 注意：使用标准差进行标准化（方差的平方根）&#10; adj_momentum &amp;lt;- momentum / sqrt(volatility)&#10; colnames(adj_momentum) &amp;lt;- &amp;quot;Adj_Momentum&amp;quot;&#10; &#10; return(list(returns = returns, &#10; momentum = momentum, &#10; volatility = volatility, &#10; adj_momentum = adj_momentum))&#10;}&#10;&#10;# 为每个ETF计算指标&#10;# cat(&amp;quot;正在计算动量指标...\n&amp;quot;)&#10;metrics_list &amp;lt;- list()&#10;for (etf in etf_names) {&#10; metrics_list[[etf]] &amp;lt;- calculate_metrics(price_df[, etf])&#10;}&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Warning in to_period(xx, period = on.opts[[period]], ...): missing values&#10;## removed from data&#10;## Warning in to_period(xx, period = on.opts[[period]], ...): missing values&#10;## removed from data&#10;## Warning in to_period(xx, period = on.opts[[period]], ...): missing values&#10;## removed from data&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# 3. 生成交易信号和权重&#10;generate_weights &amp;lt;- function(adj_momentum_df) {&#10; # 初始化权重数据框&#10; weights_df &amp;lt;- as.data.frame(adj_momentum_df)&#10; weights_df[] &amp;lt;- 0 # 所有值初始化为0&#10; &#10; # 对每一行（每个交易日）计算权重&#10; for (i in 1:nrow(adj_momentum_df)) {&#10; # 获取当日的调整动量值&#10; current_momentum &amp;lt;- as.numeric(adj_momentum_df[i, ])&#10; &#10; # 筛选调整动量大于0的标的&#10; positive_idx &amp;lt;- which(current_momentum &amp;gt; 0 &amp;amp; !is.na(current_momentum))&#10; &#10; if (length(positive_idx) &amp;gt; 0) {&#10; # 获取正的调整动量值&#10; positive_momentum &amp;lt;- current_momentum[positive_idx]&#10; &#10; # 按调整动量大小归一化计算权重&#10; normalized_weights &amp;lt;- positive_momentum / sum(positive_momentum)&#10; &#10; # 分配权重&#10; weights_df[i, positive_idx] &amp;lt;- normalized_weights&#10; }&#10; }&#10; &#10; # 转换为时间序列&#10; weights_xts &amp;lt;- xts(weights_df, order.by = index(adj_momentum_df))&#10; colnames(weights_xts) &amp;lt;- colnames(adj_momentum_df)&#10; &#10; return(weights_xts)&#10;}&#10;&#10;# 提取所有ETF的调整动量&#10;adj_momentum_all &amp;lt;- do.call(merge, lapply(metrics_list, function(x) x$adj_momentum))&#10;colnames(adj_momentum_all) &amp;lt;- etf_names&#10;&#10;# 生成权重序列&#10;# cat(&amp;quot;正在计算每日权重...\n&amp;quot;)&#10;weights &amp;lt;- generate_weights(adj_momentum_all)&#10;&#10;# 4. 将权重数据整理到数据框中&#10;# 创建每日权重数据框（包含日期）&#10;daily_weights_df &amp;lt;- data.frame(Date = index(weights))&#10;for (etf in etf_names) {&#10; daily_weights_df[[etf]] &amp;lt;- as.numeric(weights[, etf])&#10;}&#10;&#10;# 计算每个交易日的权重合计（应为1或0）&#10;daily_weights_df$权重合计 &amp;lt;- rowSums(daily_weights_df[, etf_names], na.rm = TRUE)&#10;&#10;# 创建每个ETF的单独权重数据框&#10;etf_weight_dfs &amp;lt;- list()&#10;for (etf in etf_names) {&#10; etf_weight_dfs[[etf]] &amp;lt;- data.frame(&#10; Date = index(weights),&#10; ETF = etf,&#10; Weight = as.numeric(weights[, etf])&#10; )&#10;}&#10;&#10;# 合并所有ETF权重数据框&#10;all_etf_weights_df &amp;lt;- do.call(rbind, etf_weight_dfs)&#10;&#10;# 5. 回测计算&#10;# 计算每个ETF的日收益率&#10;returns_all &amp;lt;- do.call(merge, lapply(metrics_list, function(x) x$returns))&#10;colnames(returns_all) &amp;lt;- etf_names&#10;&#10;# 调整权重的时间索引，确保与收益率对齐&#10;# 使用T日的权重在T+1日交易&#10;lagged_weights &amp;lt;- lag(weights, 1) # 权重滞后一天&#10;lagged_weights &amp;lt;- lagged_weights[index(returns_all)] # 对齐索引&#10;&#10;# 处理缺失值&#10;lagged_weights[is.na(lagged_weights)] &amp;lt;- 0&#10;&#10;# 计算策略日收益率（按T+1日开盘价计算，这里用平均价近似）&#10;strategy_returns &amp;lt;- rowSums(returns_all * lagged_weights, na.rm = TRUE)&#10;strategy_returns &amp;lt;- xts(strategy_returns, order.by = index(returns_all))&#10;colnames(strategy_returns) &amp;lt;- &amp;quot;动量策略&amp;quot;&#10;&#10;# 6. 绩效指标计算&#10;# cat(&amp;quot;正在计算绩效指标...\n&amp;quot;)&#10;# 策略绩效&#10;strategy_perf &amp;lt;- table.AnnualizedReturns(strategy_returns)&#10;strategy_dd &amp;lt;- table.DownsideRisk(strategy_returns)&#10;max_dd &amp;lt;- maxDrawdown(strategy_returns)&#10;strategy_calmar &amp;lt;- CalmarRatio(strategy_returns)&#10;strategy_sortino &amp;lt;- SortinoRatio(strategy_returns)&#10;strategy_positive_returns &amp;lt;- sum(strategy_returns &amp;gt; 0, na.rm = TRUE)&#10;strategy_total_returns &amp;lt;- sum(!is.na(strategy_returns))&#10;strategy_win_rate &amp;lt;- strategy_positive_returns / strategy_total_returns&#10;&#10;# 基准绩效（沪深300ETF）&#10;benchmark_returns &amp;lt;- returns_all[, &amp;quot;沪深300ETF&amp;quot;]&#10;colnames(benchmark_returns) &amp;lt;- &amp;quot;沪深300ETF&amp;quot;&#10;benchmark_perf &amp;lt;- table.AnnualizedReturns(benchmark_returns)&#10;benchmark_dd &amp;lt;- table.DownsideRisk(benchmark_returns)&#10;benchmark_max_dd &amp;lt;- maxDrawdown(benchmark_returns)&#10;benchmark_calmar &amp;lt;- CalmarRatio(benchmark_returns)&#10;benchmark_sortino &amp;lt;- SortinoRatio(benchmark_returns)&#10;benchmark_positive_returns &amp;lt;- sum(benchmark_returns &amp;gt; 0, na.rm = TRUE)&#10;benchmark_total_returns &amp;lt;- sum(!is.na(benchmark_returns))&#10;benchmark_win_rate &amp;lt;- benchmark_positive_returns / benchmark_total_returns&#10;&#10;# 等权重组合绩效&#10;equal_weights &amp;lt;- matrix(1/3, nrow = nrow(returns_all), ncol = ncol(returns_all))&#10;equal_weights &amp;lt;- xts(equal_weights, order.by = index(returns_all))&#10;colnames(equal_weights) &amp;lt;- etf_names&#10;equal_returns &amp;lt;- rowSums(returns_all * equal_weights, na.rm = TRUE)&#10;equal_returns &amp;lt;- xts(equal_returns, order.by = index(returns_all))&#10;colnames(equal_returns) &amp;lt;- &amp;quot;等权重组合&amp;quot;&#10;equal_perf &amp;lt;- table.AnnualizedReturns(equal_returns)&#10;equal_max_dd &amp;lt;- maxDrawdown(equal_returns)&#10;equal_calmar &amp;lt;- CalmarRatio(equal_returns)&#10;equal_sortino &amp;lt;- SortinoRatio(equal_returns)&#10;equal_positive_returns &amp;lt;- sum(equal_returns &amp;gt; 0, na.rm = TRUE)&#10;equal_total_returns &amp;lt;- sum(!is.na(equal_returns))&#10;equal_win_rate &amp;lt;- equal_positive_returns / equal_total_returns&#10;&#10;# 7. 创建绩效指标汇总数据框&#10;# 格式化日期字符串&#10;start_date_str &amp;lt;- format(start_date, &amp;quot;%Y-%m-%d&amp;quot;)&#10;end_date_str &amp;lt;- format(end_date, &amp;quot;%Y-%m-%d&amp;quot;)&#10;period_str &amp;lt;- paste(start_date_str, &amp;quot;至&amp;quot;, end_date_str)&#10;&#10;performance_metrics_df &amp;lt;- data.frame(&#10; 策略 = c(&amp;quot;动量策略&amp;quot;, &amp;quot;沪深300ETF&amp;quot;, &amp;quot;等权重组合&amp;quot;),&#10; 年化收益率 = c(&#10; round(strategy_perf[1, 1] * 100, 2),&#10; round(benchmark_perf[1, 1] * 100, 2),&#10; round(equal_perf[1, 1] * 100, 2)&#10; ),&#10; 年化波动率 = c(&#10; round(strategy_perf[2, 1] * 100, 2),&#10; round(benchmark_perf[2, 1] * 100, 2),&#10; round(equal_perf[2, 1] * 100, 2)&#10; ),&#10; 夏普比率 = c(&#10; round(strategy_perf[3, 1], 3),&#10; round(benchmark_perf[3, 1], 3),&#10; round(equal_perf[3, 1], 3)&#10; ),&#10; 最大回撤 = c(&#10; round(max_dd * 100, 2),&#10; round(benchmark_max_dd * 100, 2),&#10; round(equal_max_dd * 100, 2)&#10; ),&#10; 卡尔马比率 = c(&#10; round(strategy_calmar, 3),&#10; round(benchmark_calmar, 3),&#10; round(equal_calmar, 3)&#10; ),&#10; 索提诺比率 = c(&#10; round(strategy_sortino, 3),&#10; round(benchmark_sortino, 3),&#10; round(equal_sortino, 3)&#10; ),&#10; 胜率 = c(&#10; round(strategy_win_rate * 100, 2),&#10; round(benchmark_win_rate * 100, 2),&#10; round(equal_win_rate * 100, 2)&#10; ),&#10; 正收益天数 = c(&#10; strategy_positive_returns,&#10; benchmark_positive_returns,&#10; equal_positive_returns&#10; ),&#10; 总交易天数 = c(&#10; strategy_total_returns,&#10; benchmark_total_returns,&#10; equal_total_returns&#10; ),&#10; 回测期间 = c(period_str, period_str, period_str)&#10;)&#10;&#10;# 8. 绩效指标输出&#10;# cat(&amp;quot;==================== 绩效指标汇总数据框 ====================\n\n&amp;quot;)&#10;print(performance_metrics_df)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## 策略 年化收益率 年化波动率 夏普比率 最大回撤 卡尔马比率 索提诺比率&#10;## 1 动量策略 45.13 17.08 2.643 8.72 5.178 0.227&#10;## 2 沪深300ETF 20.31 19.27 1.054 16.25 1.250 0.103&#10;## 3 等权重组合 31.84 12.89 2.470 9.29 3.429 0.201&#10;## 胜率 正收益天数 总交易天数 回测期间&#10;## 1 53.04 253 477 2024-01-01 至 2025-12-23&#10;## 2 51.26 244 476 2024-01-01 至 2025-12-23&#10;## 3 59.33 283 477 2024-01-01 至 2025-12-23&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# cat(&amp;quot;\n&amp;quot;)&#10;&#10;# 9. 输出权重数据&#10;&#10;# cat(&amp;quot;每日组合权重数据框（后10行）:\n&amp;quot;)&#10;print(tail(daily_weights_df, 10))&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Date 纳指ETF 沪深300ETF 黄金ETF 权重合计&#10;## 468 2025-12-08 0.09379501 0.00000000 0.9062050 1&#10;## 469 2025-12-09 0.00000000 0.00000000 0.0000000 0&#10;## 470 2025-12-10 0.00000000 0.00000000 1.0000000 1&#10;## 471 2025-12-11 0.00000000 0.00000000 0.0000000 0&#10;## 472 2025-12-12 0.05889600 0.00000000 0.9411040 1&#10;## 473 2025-12-15 0.00000000 0.00000000 1.0000000 1&#10;## 474 2025-12-16 0.16844695 0.00000000 0.8315530 1&#10;## 475 2025-12-17 0.31823928 0.01791372 0.6638470 1&#10;## 476 2025-12-18 0.00000000 0.00000000 1.0000000 1&#10;## 477 2025-12-19 0.22970999 0.26353990 0.5067501 1&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# cat(&amp;quot;\n&amp;quot;)&#10;&#10;&#10;# 10. 绘制图表&#10;# cat(&amp;quot;正在生成图表...\n&amp;quot;)&#10;# 准备累计收益率数据&#10;cumulative_returns &amp;lt;- merge(&#10; cumprod(1 + na.fill(strategy_returns, 0)) - 1,&#10; cumprod(1 + na.fill(benchmark_returns, 0)) - 1,&#10; cumprod(1 + na.fill(equal_returns, 0)) - 1&#10;)&#10;colnames(cumulative_returns) &amp;lt;- c(&amp;quot;动量策略&amp;quot;, &amp;quot;沪深300ETF&amp;quot;, &amp;quot;等权重组合&amp;quot;)&#10;&#10;# 转换为数据框用于ggplot&#10;cumulative_df &amp;lt;- data.frame(&#10; Date = index(cumulative_returns),&#10; as.data.frame(cumulative_returns)&#10;)&#10;cumulative_long &amp;lt;- pivot_longer(cumulative_df, &#10; cols = -Date, &#10; names_to = &amp;quot;Portfolio&amp;quot;, &#10; values_to = &amp;quot;CumulativeReturn&amp;quot;)&#10;&#10;# 图表1：策略 vs 基准累计收益率和最大回撤对比&#10;p1 &amp;lt;- ggplot(cumulative_long %&amp;gt;% filter(Portfolio %in% c(&amp;quot;动量策略&amp;quot;, &amp;quot;沪深300ETF&amp;quot;)), &#10; aes(x = Date, y = CumulativeReturn, color = Portfolio)) +&#10; geom_line(size = 1.2) +&#10; labs(title = &amp;quot;动量策略 vs 沪深300ETF: 累计收益率对比&amp;quot;,&#10; x = &amp;quot;日期&amp;quot;, y = &amp;quot;累计收益率&amp;quot;) +&#10; scale_y_continuous(labels = percent_format()) +&#10; scale_color_manual(values = c(&amp;quot;动量策略&amp;quot; = &amp;quot;blue&amp;quot;, &amp;quot;沪深300ETF&amp;quot; = &amp;quot;red&amp;quot;)) +&#10; theme_minimal() +&#10; theme(legend.position = &amp;quot;bottom&amp;quot;,&#10; plot.title = element_text(hjust = 0.5, size = 14, face = &amp;quot;bold&amp;quot;))&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.&#10;## ℹ Please use `linewidth` instead.&#10;## This warning is displayed once every 8 hours.&#10;## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was&#10;## generated.&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# 图表2：策略 vs 各ETF Buy &amp;amp; Hold对比&#10;# 计算各ETF的累计收益率&#10;etf_cumulative &amp;lt;- do.call(merge, &#10; lapply(1:length(etf_names), &#10; function(i) cumprod(1 + na.fill(returns_all[, i], 0)) - 1))&#10;colnames(etf_cumulative) &amp;lt;- paste0(etf_names, &amp;quot; (Buy&amp;amp;Hold)&amp;quot;)&#10;&#10;all_cumulative &amp;lt;- merge(cumulative_returns[, &amp;quot;动量策略&amp;quot;], etf_cumulative)&#10;all_cumulative_df &amp;lt;- data.frame(Date = index(all_cumulative), &#10; as.data.frame(all_cumulative))&#10;all_cumulative_long &amp;lt;- pivot_longer(all_cumulative_df, &#10; cols = -Date, &#10; names_to = &amp;quot;Strategy&amp;quot;, &#10; values_to = &amp;quot;CumulativeReturn&amp;quot;)&#10;&#10;p2 &amp;lt;- ggplot(all_cumulative_long, aes(x = Date, y = CumulativeReturn, color = Strategy)) +&#10; geom_line(size = 1) +&#10; labs(title = &amp;quot;动量策略 vs 各ETF买入持有策略: 累计收益率对比&amp;quot;,&#10; x = &amp;quot;日期&amp;quot;, y = &amp;quot;累计收益率&amp;quot;) +&#10; scale_y_continuous(labels = percent_format()) +&#10; theme_minimal() +&#10; theme(legend.position = &amp;quot;bottom&amp;quot;,&#10; plot.title = element_text(hjust = 0.5, size = 14, face = &amp;quot;bold&amp;quot;))&#10;&#10;# 图表3：策略 vs 等权重组合对比&#10;p3 &amp;lt;- ggplot(cumulative_long %&amp;gt;% filter(Portfolio %in% c(&amp;quot;动量策略&amp;quot;, &amp;quot;等权重组合&amp;quot;)), &#10; aes(x = Date, y = CumulativeReturn, color = Portfolio)) +&#10; geom_line(size = 1.2) +&#10; labs(title = &amp;quot;动量策略 vs 等权重组合: 累计收益率对比&amp;quot;,&#10; x = &amp;quot;日期&amp;quot;, y = &amp;quot;累计收益率&amp;quot;) +&#10; scale_y_continuous(labels = percent_format()) +&#10; scale_color_manual(values = c(&amp;quot;动量策略&amp;quot; = &amp;quot;blue&amp;quot;, &amp;quot;等权重组合&amp;quot; = &amp;quot;green&amp;quot;)) +&#10; theme_minimal() +&#10; theme(legend.position = &amp;quot;bottom&amp;quot;,&#10; plot.title = element_text(hjust = 0.5, size = 14, face = &amp;quot;bold&amp;quot;))&#10;&#10;# 图表4：权重随时间变化图&#10;# 准备权重数据&#10;weights_long &amp;lt;- pivot_longer(daily_weights_df, &#10; cols = all_of(etf_names),&#10; names_to = &amp;quot;ETF&amp;quot;, &#10; values_to = &amp;quot;Weight&amp;quot;)&#10;&#10;p4 &amp;lt;- ggplot(weights_long, aes(x = Date, y = Weight, fill = ETF)) +&#10; geom_area(position = &amp;quot;stack&amp;quot;, alpha = 0.7) +&#10; labs(title = &amp;quot;动量策略: 每日权重分配&amp;quot;,&#10; x = &amp;quot;日期&amp;quot;, y = &amp;quot;权重&amp;quot;) +&#10; scale_y_continuous(labels = percent_format()) +&#10; scale_fill_manual(values = c(&amp;quot;纳指ETF&amp;quot; = &amp;quot;blue&amp;quot;, &#10; &amp;quot;沪深300ETF&amp;quot; = &amp;quot;red&amp;quot;, &#10; &amp;quot;黄金ETF&amp;quot; = &amp;quot;gold&amp;quot;)) +&#10; theme_minimal() +&#10; theme(legend.position = &amp;quot;bottom&amp;quot;,&#10; plot.title = element_text(hjust = 0.5, size = 14, face = &amp;quot;bold&amp;quot;))&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# 12. 显示图表&#10;# cat(&amp;quot;\n正在显示图表...\n&amp;quot;)&#10;print(p1)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;&lt;img src="https://gewutang.cn/2025/12/23/all-weather-momentum/index_files/figure-html/unnamed-chunk-2-1.png" width="672" /&gt;&lt;/p&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# cat(&amp;quot;\n\n&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;print(p2)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;&lt;img src="https://gewutang.cn/2025/12/23/all-weather-momentum/index_files/figure-html/unnamed-chunk-3-1.png" width="672" /&gt;&lt;/p&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# cat(&amp;quot;\n\n&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;print(p3)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;&lt;img src="https://gewutang.cn/2025/12/23/all-weather-momentum/index_files/figure-html/unnamed-chunk-4-1.png" width="672" /&gt;&lt;/p&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# cat(&amp;quot;\n\n&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;print(p4)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;&lt;img src="https://gewutang.cn/2025/12/23/all-weather-momentum/index_files/figure-html/unnamed-chunk-5-1.png" width="672" /&gt;&lt;/p&gt;&#10;</description></item><item><title>投资笔记 1 ：先立认知，再选策略</title><link>https://gewutang.cn/2025/11/14/notes-on-investments/</link><pubDate>Fri, 14 Nov 2025 00:00:00 +0000</pubDate><guid>https://gewutang.cn/2025/11/14/notes-on-investments/</guid><description>&#10;&#10;&#10;&lt;p&gt;投资成功需以三大核心为前提：系统的投资知识储备、知名机构与大师的实践参考、贴合自身的个性化策略。脱离这些前提，即便偶遇短期行情，也可能因方向偏差、风险误判导致亏损。&lt;/p&gt;&#10;&lt;p&gt;本 “投资必读” 系列共 10&#10;篇文章，后续将系统拆解各类策略的逻辑框架、实操方法与适用范围，结合领域内知名机构与投资大师的实践案例提供参考。本篇作为开篇，核心是建立&#10;“先学知识、再判机会、后选策略”&#10;的底层认知，厘清被动与主动策略的本质差异与适配逻辑。&lt;/p&gt;&#10;&lt;div id="一投资的底层共识" class="section level2"&gt;&#10;&lt;h2&gt;一、投资的底层共识&lt;/h2&gt;&#10;&lt;p&gt;投资策略选择的优先级远高于具体产品筛选。合理的策略能在控制风险的同时最大化收益；若策略逻辑偏差，即便选择优质标的，也可能因市场适配错误或偏离收益目标导致亏损。&lt;/p&gt;&#10;&lt;p&gt;盲目投资本质是 “无准备入场”，必然面临三重风险：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;市场类型错配：将弱有效市场（如 A&#10;股创业板）的主动策略逻辑，套用到强有效市场（如美股标普&#10;500），用高费率主动基金博弈市场平均收益，最终&#10;“费力不讨好”；&lt;/li&gt;&#10;&lt;li&gt;操作逻辑混淆：误将被动跟踪的长期逻辑用于短期波段操作，如用沪深&#10;300ETF&#10;频繁追涨杀跌，既增加交易成本，又错失指数长期复利；&lt;/li&gt;&#10;&lt;li&gt;资金需求偏离：中短期低风险需求（如 3&#10;年后子女教育资金）却配置高波动主动权益基金，市场回撤时被迫割肉离场。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;因此，投资的第一步是&#10;“学知识、定目标”，明确收益目标、风险容忍度、资金周期，再选择适配的投资策略。&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div id="二策略核心分类被动与主动的本质差异-依据" class="section level2"&gt;&#10;&lt;h2&gt;二、策略核心分类：被动与主动的本质差异 依据&lt;/h2&gt;&#10;&lt;p&gt;“是否主动追求超额收益（Alpha&#10;收益）”，投资策略可划分为被动管理与主动管理两大体系，适配不同市场环境与投资需求。&lt;/p&gt;&#10;&lt;p&gt;1.被动管理策略：赚市场平均的确定性收益&lt;/p&gt;&#10;&lt;p&gt;被动管理策略的本质是&#10;“以指数为基准，通过复制指数成分股构成与权重，实现与基准收益（Beta&#10;收益）的高度重合”，核心目标是获取市场平均收益。&lt;/p&gt;&#10;&lt;p&gt;其理论基础是&#10;“市场有效性假说（EMH）”：在信息充分反映的强有效市场中，主动决策难以持续创造超额收益，被动策略成为最优选择。先锋集团创始人约翰・博格尔提出的&#10;“低成本、长期持有”，是被动策略的核心原则。&lt;/p&gt;&#10;&lt;p&gt;主流产品类型与操作要点&#10;* 纯被动指数基金 /&#10;ETF：完全复制指数成分股与权重，无主动调整，跟踪误差通常低于&#10;0.5%。优先选择低费率（管理费率低于&#10;0.15%）、高流动性（日均成交额超 1&#10;亿元）的产品，例如华夏沪深&#10;300ETF（510330）、易方达标普 500ETF（513500）。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;p&gt;指数增强基金：在被动跟踪基础上小幅调整，通过量化模型或基本面分析对成分股进行不超过&#10;5% 的超配 / 低配，控制跟踪误差（通常低于&#10;2%）并追求少量超额收益。选择时重点关注连续 3&#10;年跑赢基准的稳定性，例如富国沪深 300&#10;增强（100038）。&lt;/p&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;p&gt;被动型&#10;FOF：通过配置多只被动基金实现跨资产、跨市场分散，降低单一指数波动风险。关注资产配置比例与自身风险偏好的契合度，以及总费率（通常不超过&#10;1%），例如南方智诚 FOF（008988）。 适配投资者画像&#10;投资周期超 3&#10;年、风险偏好中低（年化波动率容忍度低于&#10;10%）、无专业研究能力的个人投资者，核心需求是&#10;“稳定获取长期收益”。&lt;/p&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;2.主动管理策略：赚超越市场的机会性收益&lt;/p&gt;&#10;&lt;p&gt;主动管理策略通过资产筛选、择时决策与组合调整，突破市场有效性边界，追求超额收益（Alpha&#10;收益）。核心逻辑是依赖专业研究或量化模型，发现市场定价偏差。&#10;该策略需承担更高成本：管理费率通常&#10;1%-2%，波动风险更大，且仅在弱有效或半强有效市场（如&#10;A 股创业板、印度股市）更易见效 ——&#10;这类市场信息传递效率低、机构持股比例低，存在更多定价偏差机会。&#10;经典案例&#10;伯克希尔・哈撒韦：巴菲特通过深度基本面分析，聚焦&#10;“护城河深厚、现金流稳定”&#10;的企业，长期持有并主动调整组合，50 余年复合年化超&#10;20%； 富达麦哲伦基金：彼得・林奇通过 “草根调研”&#10;挖掘成长股，13 年间规模从 2000 万美元增至 140&#10;亿美元，年化收益超 29%。 适配投资者画像 投资周期 3&#10;年以上、风险偏好中高（年化波动率容忍度&#10;10%-20%）、具备一定研究能力或可依托专业投顾的投资者，愿意为超额收益承担更高波动。&lt;/p&gt;&#10;&lt;ol start="3" style="list-style-type: decimal"&gt;&#10;&lt;li&gt;被动与主动的适用边界&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;两者的核心差异由“市场有效性” 决定，适配不同投资场景：&lt;/p&gt;&#10;&lt;table&gt;&#10;&lt;colgroup&gt;&#10;&lt;col width="33%" /&gt;&#10;&lt;col width="33%" /&gt;&#10;&lt;col width="33%" /&gt;&#10;&lt;/colgroup&gt;&#10;&lt;thead&gt;&#10;&lt;tr class="header"&gt;&#10;&lt;th align="left"&gt;维度&lt;/th&gt;&#10;&lt;th align="left"&gt;被动管理策略（循标航行）&lt;/th&gt;&#10;&lt;th align="left"&gt;主动管理策略（探路航行）&lt;/th&gt;&#10;&lt;/tr&gt;&#10;&lt;/thead&gt;&#10;&lt;tbody&gt;&#10;&lt;tr class="odd"&gt;&#10;&lt;td align="left"&gt;市场环境&lt;/td&gt;&#10;&lt;td align="left"&gt;强有效市场（如美股标普 500、A 股沪深 300）&lt;/td&gt;&#10;&lt;td align="left"&gt;弱 / 半强有效市场（如 A 股创业板、新兴市场）&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="even"&gt;&#10;&lt;td align="left"&gt;核心目标&lt;/td&gt;&#10;&lt;td align="left"&gt;获取市场平均收益（Beta）&lt;/td&gt;&#10;&lt;td align="left"&gt;获取超额收益（Alpha）&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="odd"&gt;&#10;&lt;td align="left"&gt;成本与风险&lt;/td&gt;&#10;&lt;td align="left"&gt;低费率（0.03%-0.5%）、低波动&lt;/td&gt;&#10;&lt;td align="left"&gt;高费率（1%-2%）、高波动&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="even"&gt;&#10;&lt;td align="left"&gt;操作逻辑&lt;/td&gt;&#10;&lt;td align="left"&gt;放弃择时与选股，长期持有&lt;/td&gt;&#10;&lt;td align="left"&gt;主动择时、选股，动态调整组合&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="odd"&gt;&#10;&lt;td align="left"&gt;长期收益概率&lt;/td&gt;&#10;&lt;td align="left"&gt;大概率跑赢多数主动策略&lt;/td&gt;&#10;&lt;td align="left"&gt;需筛选优质管理人，少数能持续跑赢&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;简言之：强有效市场中，被动策略更省心划算；弱 /&#10;半强有效市场中，主动策略可赚取 “认知差” 收益。&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div id="三投资行动准则先判机会再选策略" class="section level2"&gt;&#10;&lt;h2&gt;三、投资行动准则：先判机会，再选策略&lt;/h2&gt;&#10;&lt;p&gt;掌握策略逻辑后，投资的关键是&#10;“先判断市场机会，再选择适配策略”，而非盲目入场。&lt;/p&gt;&#10;&lt;ol style="list-style-type: decimal"&gt;&#10;&lt;li&gt;何时持有现金？&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;市场缺乏明确机会或处于高风险区间时，持有现金是更稳妥的选择：&#10;市场估值过高（如 2021 年 A&#10;股白酒、新能源板块估值分位超 90%），易面临&#10;“高位站岗” 风险；&#10;市场情绪极端狂热（散户开户数激增、全民讨论股市）或宏观环境不确定性高（如&#10;2020 年疫情初期、2022&#10;年全球加息周期），等待机会比盲目入场更明智。&#10;现金是&#10;“等待机会的弹药”，可在优质投资机会出现时快速布局。&lt;/p&gt;&#10;&lt;ol start="2" style="list-style-type: decimal"&gt;&#10;&lt;li&gt;何时选择策略？&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;市场出现明确机会信号时，结合四大维度选择被动或主动策略：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;p&gt;资金周期：短期资金（1-2&#10;年，如购房首付）选被动策略，流动性高、波动小；长期资金（5&#10;年以上，如养老储备）可选主动策略或指数增强，更易消化短期波动；&lt;/p&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;p&gt;资金规模：小额资金（10 万以内）选被动&#10;ETF，成本低、操作灵活；大额资金（100&#10;万以上）可搭配被动 FOF +&#10;少量优质主动基金，实现攻守平衡；&lt;/p&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;p&gt;风险偏好：中低风险（如退休人群，最大回撤容忍度低于&#10;10%）可选 “被动宽基 + 债券 ETF” 组合；中高风险（如&#10;30 岁上班族，最大回撤容忍度低于&#10;20%）可选指数增强或优质主动基金；&lt;/p&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;p&gt;预期收益：追求&#10;“稳”（年化 6%-8%）选被动；追求 “优”（年化&#10;8%-12%）且能承担波动，选主动。 示例：35&#10;岁上班族每月结余 5000 元，计划 10&#10;年后用于子女留学（资金周期 10 年、风险容忍度&#10;15%、预期年化 8%-10%），可每月定投 50% 富国沪深&#10;300 增强（指数增强）+50% 易方达标普&#10;500ETF（纯被动），平衡风险与收益。&lt;/p&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/div&gt;&#10;&lt;div id="四投资的平衡之道守正与出奇" class="section level2"&gt;&#10;&lt;h2&gt;四、投资的平衡之道：守正与出奇&lt;/h2&gt;&#10;&lt;p&gt;被动与主动策略的核心是 “守正” 与 “出奇”&#10;的平衡：被动策略&#10;“守正”，以低成本、高确定性跟上市场；主动策略&#10;“出奇”，以专业能力博取超额收益。无论选择哪种，前提都是&#10;“先学知识、再定目标、后判机会”。&lt;/p&gt;&#10;&lt;p&gt;本系列后续将进一步拆解主动管理策略的具体逻辑（如价值投资、成长投资、量化策略）、不同市场周期的策略调整技巧，以及桥水、高瓴等机构的实践案例，提供更细致的指南。&#10;投资不是 “赌运气”，而是&#10;“先做准备、再等机会、选对方法”，唯有如此，才能在长期投资中稳步抵达目标。&lt;/p&gt;&#10;&lt;/div&gt;&#10;</description></item><item><title>A 股最近的表现怎么样</title><link>https://gewutang.cn/2025/08/23/performance-of-ashare/</link><pubDate>Sat, 23 Aug 2025 00:00:00 +0000</pubDate><guid>https://gewutang.cn/2025/08/23/performance-of-ashare/</guid><description>&#10;&#10;&#10;&lt;p&gt;本轮A股行情从2024年9月份启动到现在，上证指数已累计上涨了9.4%，深成指累计上涨12.9%，创业板指数累计上涨了33.7%。可谓汹涌上涨、波澜壮阔。&lt;/p&gt;&#10;&lt;p&gt;抓住了这波行情的投资者不用说自然是喜不胜收，那些错失前期行情的投资者，也开始抵挡不住赚钱的诱惑准备上车了。不过，千万不要太过性急！&lt;/p&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# 安装必要包（若未安装）&#10;# install.packages(c(&amp;quot;quantmod&amp;quot;, &amp;quot;ggplot2&amp;quot;, &amp;quot;TTR&amp;quot;, &amp;quot;scales&amp;quot;, &amp;quot;gridExtra&amp;quot;, &amp;quot;cowplot&amp;quot;, &amp;quot;showtext&amp;quot;))&#10;&#10;library(quantmod)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Loading required package: xts&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Loading required package: zoo&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## &#10;## Attaching package: &amp;#39;zoo&amp;#39;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## The following objects are masked from &amp;#39;package:base&amp;#39;:&#10;## &#10;## as.Date, as.Date.numeric&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Loading required package: TTR&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Registered S3 method overwritten by &amp;#39;quantmod&amp;#39;:&#10;## method from&#10;## as.zoo.data.frame zoo&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;library(ggplot2)&#10;library(TTR)&#10;library(scales)&#10;library(gridExtra)&#10;library(cowplot)&#10;library(showtext)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Loading required package: sysfonts&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Loading required package: showtextdb&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# 设置中文字体&#10;font_add(&amp;quot;SimHei&amp;quot;, &amp;quot;SimHei.ttf&amp;quot;) # 请确保系统中有SimHei字体，或指定正确路径&#10;showtext_auto()&#10;&#10;# 设置指数代码和名称&#10;indices &amp;lt;- list(&#10; &amp;quot;上证指数&amp;quot; = &amp;quot;000001.SS&amp;quot;,&#10; &amp;quot;沪深300&amp;quot; = &amp;quot;000300.SS&amp;quot;,&#10; &amp;quot;深证成指&amp;quot; = &amp;quot;399001.SZ&amp;quot;&#10;)&#10;&#10;# 获取数据（最近365天）&#10;get_stock_data &amp;lt;- function(symbol) {&#10; data &amp;lt;- tryCatch({&#10; getSymbols(symbol, src = &amp;quot;yahoo&amp;quot;, from = Sys.Date() - 365, auto.assign = FALSE)&#10; }, error = function(e) {&#10; message(paste(&amp;quot;获取数据失败:&amp;quot;, symbol, &amp;quot;-&amp;quot;, e$message))&#10; return(NULL)&#10; })&#10; return(data)&#10;}&#10;&#10;# 计算技术指标并准备数据&#10;prepare_data &amp;lt;- function(data, index_name) {&#10; if (is.null(data) || nrow(data) &amp;lt; 30) {&#10; message(paste(&amp;quot;数据不足或为空:&amp;quot;, index_name))&#10; return(NULL)&#10; }&#10; &#10; df &amp;lt;- data.frame(Date = index(data), coredata(data))&#10; colnames(df) &amp;lt;- c(&amp;quot;Date&amp;quot;, &amp;quot;Open&amp;quot;, &amp;quot;High&amp;quot;, &amp;quot;Low&amp;quot;, &amp;quot;Close&amp;quot;, &amp;quot;Volume&amp;quot;, &amp;quot;Adjusted&amp;quot;)&#10; &#10; # 计算收益率&#10; df$Return &amp;lt;- c(NA, diff(log(df$Close)))&#10; &#10; # 计算移动平均线&#10; df$SMA5 &amp;lt;- SMA(df$Close, n = 5)&#10; df$SMA20 &amp;lt;- SMA(df$Close, n = 20)&#10; df$SMA60 &amp;lt;- SMA(df$Close, n = 60)&#10; &#10; # 确保有足够的数据计算指标&#10; if (nrow(df) &amp;gt; 26) {&#10; # 计算MACD&#10; macd_data &amp;lt;- tryCatch({&#10; MACD(df$Close, nFast = 12, nSlow = 26, nSig = 9)&#10; }, error = function(e) {&#10; message(paste(&amp;quot;计算MACD失败:&amp;quot;, index_name, &amp;quot;-&amp;quot;, e$message))&#10; return(NULL)&#10; })&#10; &#10; if (!is.null(macd_data)) {&#10; df$MACD &amp;lt;- macd_data[, &amp;quot;macd&amp;quot;]&#10; df$Signal &amp;lt;- macd_data[, &amp;quot;signal&amp;quot;]&#10; df$Histogram &amp;lt;- df$MACD - df$Signal&#10; }&#10; }&#10; &#10; if (nrow(df) &amp;gt; 14) {&#10; # 计算KDJ指标&#10; kdj &amp;lt;- tryCatch({&#10; stoch(df[, c(&amp;quot;High&amp;quot;, &amp;quot;Low&amp;quot;, &amp;quot;Close&amp;quot;)], nFastK = 14, nFastD = 3, nSlowD = 3)&#10; }, error = function(e) {&#10; message(paste(&amp;quot;计算KDJ失败:&amp;quot;, index_name, &amp;quot;-&amp;quot;, e$message))&#10; return(NULL)&#10; })&#10; &#10; if (!is.null(kdj)) {&#10; df$K &amp;lt;- kdj[, &amp;quot;fastK&amp;quot;] * 100 # 转换为百分比&#10; df$D &amp;lt;- kdj[, &amp;quot;fastD&amp;quot;] * 100 # 转换为百分比&#10; df$J &amp;lt;- 3 * df$K - 2 * df$D # J线计算&#10; }&#10; &#10; # 计算RSI&#10; df$RSI &amp;lt;- tryCatch({&#10; RSI(df$Close, n = 14)&#10; }, error = function(e) {&#10; message(paste(&amp;quot;计算RSI失败:&amp;quot;, index_name, &amp;quot;-&amp;quot;, e$message))&#10; return(rep(NA, nrow(df)))&#10; })&#10; }&#10; &#10; df$Index &amp;lt;- index_name&#10; return(df)&#10;}&#10;&#10;# 获取所有指数数据&#10;all_data &amp;lt;- list()&#10;for (index_name in names(indices)) {&#10; symbol &amp;lt;- indices[[index_name]]&#10; data &amp;lt;- get_stock_data(symbol)&#10; if (!is.null(data)) {&#10; prepared_data &amp;lt;- prepare_data(data, index_name)&#10; if (!is.null(prepared_data)) {&#10; all_data[[index_name]] &amp;lt;- prepared_data&#10; }&#10; }&#10;}&#10;&#10;# 如果没有获取到任何数据，则停止执行&#10;if (length(all_data) == 0) {&#10; stop(&amp;quot;未能获取到任何指数数据，请检查网络连接和代码设置&amp;quot;)&#10;}&#10;&#10;# 合并所有数据&#10;combined_data &amp;lt;- do.call(rbind, all_data)&#10;&#10;# 1. 单独绘制价格走势图&#10;price_plot &amp;lt;- ggplot(combined_data, aes(x = Date, y = Close, color = Index)) +&#10; geom_line(size = 0.8) +&#10; theme_bw() +&#10; theme(&#10; axis.title.x = element_blank(),&#10; axis.title.y = element_blank(),&#10; legend.position = &amp;quot;bottom&amp;quot;,&#10; text = element_text(family = &amp;quot;SimHei&amp;quot;)&#10; ) +&#10; scale_color_brewer(palette = &amp;quot;Set1&amp;quot;) +&#10; scale_y_continuous(labels = comma) +&#10; # 为深证成指添加右侧Y轴&#10; scale_y_continuous(&#10; sec.axis = sec_axis(&#10; ~./max(combined_data$Close[combined_data$Index == &amp;quot;深证成指&amp;quot;], na.rm = TRUE) * &#10; max(combined_data$Close[combined_data$Index != &amp;quot;深证成指&amp;quot;], na.rm = TRUE),&#10; name = &amp;quot;深证成指&amp;quot;&#10; )&#10; )&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.&#10;## ℹ Please use `linewidth` instead.&#10;## This warning is displayed once every 8 hours.&#10;## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was&#10;## generated.&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Scale for y is already present.&#10;## Adding another scale for y, which will replace the existing scale.&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;print(price_plot)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;&lt;img src="https://gewutang.cn/2025/08/23/performance-of-ashare/index_files/figure-html/unnamed-chunk-1-1.png" width="672" /&gt;&lt;/p&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# 2. 单独绘制收益率走势图&#10;return_range &amp;lt;- range(combined_data$Return, na.rm = TRUE)&#10;&#10;return_plot &amp;lt;- ggplot(combined_data, aes(x = Date, y = Return, color = Index)) +&#10; geom_line(size = 0.8) +&#10; theme_bw() +&#10; theme(&#10; axis.title.x = element_blank(),&#10; axis.title.y = element_blank(),&#10; legend.position = &amp;quot;bottom&amp;quot;,&#10; text = element_text(family = &amp;quot;SimHei&amp;quot;)&#10; ) +&#10; scale_color_brewer(palette = &amp;quot;Set1&amp;quot;) +&#10; scale_y_continuous(labels = percent, limits = return_range)&#10;&#10;print(return_plot)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Warning: Removed 3 rows containing missing values or values outside the scale range&#10;## (`geom_line()`).&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;&lt;img src="https://gewutang.cn/2025/08/23/performance-of-ashare/index_files/figure-html/unnamed-chunk-1-2.png" width="672" /&gt;&lt;/p&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# 为每个指数单独绘制技术分析图&#10;for (index_name in names(all_data)) {&#10; index_data &amp;lt;- all_data[[index_name]]&#10; &#10; # 筛选最近三个月的数据&#10; three_months_ago &amp;lt;- Sys.Date() - 90&#10; recent_data &amp;lt;- index_data[index_data$Date &amp;gt;= three_months_ago, ]&#10; &#10; # 创建蜡烛图&#10; candle_plot &amp;lt;- ggplot(recent_data, aes(x = Date)) +&#10; geom_linerange(aes(ymin = Low, ymax = High), color = &amp;quot;black&amp;quot;, size = 0.3) +&#10; geom_rect(aes(xmin = Date - 0.4, xmax = Date + 0.4, &#10; ymin = pmin(Open, Close), ymax = pmax(Open, Close),&#10; fill = Close &amp;gt; Open), color = &amp;quot;black&amp;quot;) +&#10; geom_line(aes(y = SMA5, color = &amp;quot;SMA5&amp;quot;), size = 0.8) +&#10; geom_line(aes(y = SMA20, color = &amp;quot;SMA20&amp;quot;), size = 0.8) +&#10; geom_line(aes(y = SMA60, color = &amp;quot;SMA60&amp;quot;), size = 0.8) +&#10; scale_fill_manual(values = c(&amp;quot;TRUE&amp;quot; = &amp;quot;red&amp;quot;, &amp;quot;FALSE&amp;quot; = &amp;quot;green&amp;quot;), guide = FALSE) +&#10; scale_color_manual(values = c(&amp;quot;SMA5&amp;quot; = &amp;quot;blue&amp;quot;, &amp;quot;SMA20&amp;quot; = &amp;quot;orange&amp;quot;, &amp;quot;SMA60&amp;quot; = &amp;quot;purple&amp;quot;)) +&#10; theme_bw() +&#10; theme(&#10; axis.title.x = element_blank(),&#10; axis.title.y = element_blank(),&#10; axis.text.x = element_blank(),&#10; legend.position = &amp;quot;top&amp;quot;,&#10; legend.title = element_blank(),&#10; plot.margin = unit(c(5.5, 5.5, 0, 5.5), &amp;quot;points&amp;quot;),&#10; text = element_text(family = &amp;quot;SimHei&amp;quot;)&#10; )&#10; &#10; # 成交量图&#10; volume_plot &amp;lt;- ggplot(recent_data, aes(x = Date, y = Volume)) +&#10; geom_col(fill = &amp;quot;orange&amp;quot;, alpha = 0.7) +&#10; theme_bw() +&#10; theme(&#10; axis.title.x = element_blank(),&#10; axis.title.y = element_blank(),&#10; axis.text.x = element_blank(),&#10; plot.margin = unit(c(0, 5.5, 0, 5.5), &amp;quot;points&amp;quot;),&#10; text = element_text(family = &amp;quot;SimHei&amp;quot;)&#10; ) +&#10; scale_y_continuous(labels = comma)&#10; &#10; # MACD图&#10; macd_plot &amp;lt;- ggplot(recent_data, aes(x = Date)) +&#10; geom_line(aes(y = MACD, color = &amp;quot;MACD&amp;quot;), size = 0.8) +&#10; geom_line(aes(y = Signal, color = &amp;quot;Signal&amp;quot;), size = 0.8) +&#10; geom_col(aes(y = Histogram, fill = &amp;quot;Histogram&amp;quot;), alpha = 0.5) +&#10; geom_hline(yintercept = 0, linetype = &amp;quot;dashed&amp;quot;, color = &amp;quot;gray&amp;quot;) +&#10; scale_color_manual(values = c(&amp;quot;MACD&amp;quot; = &amp;quot;blue&amp;quot;, &amp;quot;Signal&amp;quot; = &amp;quot;red&amp;quot;)) +&#10; scale_fill_manual(values = c(&amp;quot;Histogram&amp;quot; = &amp;quot;gray&amp;quot;)) +&#10; theme_bw() +&#10; theme(&#10; axis.title.x = element_blank(),&#10; axis.title.y = element_blank(),&#10; axis.text.x = element_blank(),&#10; legend.position = &amp;quot;none&amp;quot;,&#10; plot.margin = unit(c(0, 5.5, 0, 5.5), &amp;quot;points&amp;quot;),&#10; text = element_text(family = &amp;quot;SimHei&amp;quot;)&#10; )&#10; &#10; # RSI图&#10; rsi_plot &amp;lt;- ggplot(recent_data, aes(x = Date, y = RSI)) +&#10; geom_line(color = &amp;quot;purple&amp;quot;, size = 0.8) +&#10; geom_hline(yintercept = c(30, 70), linetype = &amp;quot;dashed&amp;quot;, color = &amp;quot;red&amp;quot;) +&#10; geom_hline(yintercept = 50, linetype = &amp;quot;dashed&amp;quot;, color = &amp;quot;gray&amp;quot;) +&#10; theme_bw() +&#10; theme(&#10; axis.title.x = element_blank(),&#10; axis.title.y = element_blank(),&#10; axis.text.x = element_blank(),&#10; plot.margin = unit(c(0, 5.5, 0, 5.5), &amp;quot;points&amp;quot;),&#10; text = element_text(family = &amp;quot;SimHei&amp;quot;)&#10; ) +&#10; ylim(0, 100)&#10; &#10; # KDJ图（保留日期标签）&#10; kdj_plot &amp;lt;- ggplot(recent_data, aes(x = Date)) +&#10; geom_line(aes(y = K, color = &amp;quot;K&amp;quot;), size = 0.8) +&#10; geom_line(aes(y = D, color = &amp;quot;D&amp;quot;), size = 0.8) +&#10; geom_line(aes(y = J, color = &amp;quot;J&amp;quot;), size = 0.8) +&#10; geom_hline(yintercept = c(20, 80), linetype = &amp;quot;dashed&amp;quot;, color = &amp;quot;gray&amp;quot;) +&#10; scale_color_manual(values = c(&amp;quot;K&amp;quot; = &amp;quot;blue&amp;quot;, &amp;quot;D&amp;quot; = &amp;quot;red&amp;quot;, &amp;quot;J&amp;quot; = &amp;quot;green&amp;quot;)) +&#10; theme_bw() +&#10; theme(&#10; axis.title.x = element_blank(),&#10; axis.title.y = element_blank(),&#10; legend.position = &amp;quot;top&amp;quot;,&#10; legend.title = element_blank(),&#10; plot.margin = unit(c(0, 5.5, 5.5, 5.5), &amp;quot;points&amp;quot;),&#10; text = element_text(family = &amp;quot;SimHei&amp;quot;)&#10; ) +&#10; ylim(0, 100)&#10; &#10; # 组合图表&#10; index_plot &amp;lt;- plot_grid(&#10; candle_plot,&#10; volume_plot,&#10; macd_plot,&#10; rsi_plot,&#10; kdj_plot,&#10; ncol = 1,&#10; align = &amp;quot;v&amp;quot;,&#10; rel_heights = c(2, 1, 1, 1, 1.2)&#10; )&#10; &#10; final_plot &amp;lt;- plot_grid(&#10; title, index_plot,&#10; ncol = 1,&#10; rel_heights = c(0.05, 1)&#10; )&#10; &#10; # 显示图表&#10; print(final_plot)&#10;}&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Warning: The `guide` argument in `scale_*()` cannot be `FALSE`. This was deprecated in&#10;## ggplot2 3.3.4.&#10;## ℹ Please use &amp;quot;none&amp;quot; instead.&#10;## This warning is displayed once every 8 hours.&#10;## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was&#10;## generated.&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family&#10;## &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family&#10;## &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family&#10;## &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family&#10;## &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family&#10;## &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family&#10;## &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family&#10;## &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family&#10;## &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family&#10;## &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family&#10;## &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family&#10;## &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family&#10;## &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family&#10;## &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family&#10;## &amp;#39;SimHei&amp;#39; not found in PostScript font database&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Warning: Removed 3 rows containing missing values or values outside the scale range&#10;## (`geom_line()`).&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Warning: Package `gridGraphics` is required to handle base-R plots.&#10;## Substituting empty plot.&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Warning: Removed 3 rows containing missing values or values outside the scale range&#10;## (`geom_line()`).&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;&lt;img src="https://gewutang.cn/2025/08/23/performance-of-ashare/index_files/figure-html/unnamed-chunk-1-3.png" width="672" /&gt;&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;## Warning: Package `gridGraphics` is required to handle base-R plots.&#10;## Substituting empty plot.&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning: font family &amp;#39;SimHei&amp;#39; not found in PostScript font database&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Warning: Removed 3 rows containing missing values or values outside the scale range&#10;## (`geom_line()`).&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&#10;## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font&#10;## family &amp;#39;SimHei&amp;#39; not found in PostScript font database&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;&lt;img src="https://gewutang.cn/2025/08/23/performance-of-ashare/index_files/figure-html/unnamed-chunk-1-4.png" width="672" /&gt;&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;## Warning: Package `gridGraphics` is required to handle base-R plots.&#10;## Substituting empty plot.&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;&lt;img src="https://gewutang.cn/2025/08/23/performance-of-ashare/index_files/figure-html/unnamed-chunk-1-5.png" width="672" /&gt;&lt;/p&gt;&#10;</description></item><item><title>使用卡尔曼滤波计算个股的动态贝塔</title><link>https://gewutang.cn/2025/08/23/kalman-beta/</link><pubDate>Sat, 23 Aug 2025 00:00:00 +0000</pubDate><guid>https://gewutang.cn/2025/08/23/kalman-beta/</guid><description>&#10;&#10;&#10;&lt;div id="引言" class="section level1"&gt;&#10;&lt;h1&gt;引言&lt;/h1&gt;&#10;&lt;p&gt;在金融领域，贝塔（β）系数是资本资产定价模型（CAPM）中的核心参数，用于衡量单个资产或证券组合相对于整个市场（通常以市场指数代表）的系统性风险或波动性。具体而言，贝塔反映了市场收益率变动一个单位时，个体资产收益率的预期变动幅度。准确估计贝塔对于投资组合管理、风险控制、资产定价以及绩效评估都具有重要意义。例如，投资者可通过贝值判断资产的风险属性，进行合理的资产配置；基金经理也可依据贝塔调整投资组合的市场暴露程度。&lt;/p&gt;&#10;&lt;p&gt;传统的贝塔估计方法主要依赖于最小二乘（OLS）回归。通过在给定时间窗口（如1年、3年或5年）内对资产收益率与市场收益率进行线性回归，所得斜率系数即为贝塔估计值。此外，为降低短期波动带来的误差，也常采用滚动窗口回归或调整贝塔（Adjusted Beta）等方法。&lt;/p&gt;&#10;&lt;p&gt;然而，这些传统方法存在明显不足。首先，它们隐含假设贝塔在估计期间内是固定不变的，但事实上，受公司资本结构、经营策略、行业竞争及宏观经济环境等因素影响，资产的系统性风险可能随时间变化，即贝塔具有时变性。其次，滚动窗口回归中窗口长度的选择缺乏统一标准，较短窗口对噪声敏感，较长窗口则可能无法及时捕捉最新变化。再者，这些方法无法提供实时更新的贝塔估计，难以满足动态风险管理的需求。&lt;/p&gt;&#10;&lt;p&gt;为克服上述不足，本研究引入卡尔曼滤波（Kalman Filter）方法进行时变贝塔的估计。卡尔曼滤波是一种递归状态估计算法，能够从带有噪声的观测数据中最优地估计动态系统的内部状态。其核心优势在于能够实时更新状态估计，并通过建模状态变量的动态演化过程（如随机游走）来捕捉参数的时变特性。将卡尔曼滤波应用于贝塔估计，不仅可以得到随时间平滑变化的贝塔序列，还能通过状态空间模型灵活描述贝塔的动态行为，从而提供更准确、适应性的风险度量。&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div id="卡尔曼滤波原理及其在计算贝塔中的应用" class="section level1"&gt;&#10;&lt;h1&gt;卡尔曼滤波原理及其在计算贝塔中的应用&lt;/h1&gt;&#10;&lt;p&gt;卡尔曼滤波是一种最优递归数据处理算法，用于从一系列存在噪声的观测数据中估计动态系统的内部状态。其基本思想是通过结合系统模型的预测（先验估计）和当前观测值的更新，递归地得到状态的最优估计（后验估计）。该算法主要包含两个步骤：预测（时间更新）和更新（测量更新）。&lt;/p&gt;&#10;&lt;div id="基本原理" class="section level2"&gt;&#10;&lt;h2&gt;基本原理&lt;/h2&gt;&#10;&lt;ol style="list-style-type: decimal"&gt;&#10;&lt;li&gt;&lt;strong&gt;状态空间模型&lt;/strong&gt;&lt;br /&gt;&#10;卡尔曼滤波建立在状态空间模型之上，包括状态方程和观测方程：&#10;&lt;ul&gt;&#10;&lt;li&gt;状态方程（系统模型）：描述状态向量如何随时间演化&lt;br /&gt;&#10;&lt;span class="math display"&gt;\[x_t = F_t x_{t-1} + B_t u_t + w_t\]&lt;/span&gt;&lt;br /&gt;&#10;其中，&lt;span class="math inline"&gt;\(x_t\)&lt;/span&gt;为&lt;span class="math inline"&gt;\(t\)&lt;/span&gt;时刻的状态向量，&lt;span class="math inline"&gt;\(F_t\)&lt;/span&gt;为状态转移矩阵，&lt;span class="math inline"&gt;\(u_t\)&lt;/span&gt;为控制输入向量（可选），&lt;span class="math inline"&gt;\(B_t\)&lt;/span&gt;为控制输入矩阵，&lt;span class="math inline"&gt;\(w_t \sim N(0, Q_t)\)&lt;/span&gt;为过程噪声。&lt;br /&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;观测方程（测量模型）：描述观测值与状态向量的关系&lt;br /&gt;&#10;&lt;span class="math display"&gt;\[z_t = H_t x_t + v_t\]&lt;/span&gt;&lt;br /&gt;&#10;其中，&lt;span class="math inline"&gt;\(z_t\)&lt;/span&gt;为&lt;span class="math inline"&gt;\(t\)&lt;/span&gt;时刻的观测向量，&lt;span class="math inline"&gt;\(H_t\)&lt;/span&gt;为观测矩阵，&lt;span class="math inline"&gt;\(v_t \sim N(0, R_t)\)&lt;/span&gt;为观测噪声。&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;算法步骤&lt;/strong&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;预测步骤&lt;/strong&gt;：&lt;br /&gt;&#10;先验状态估计：&lt;br /&gt;&#10;&lt;span class="math display"&gt;\[\hat{x}_t^{-} = F_t \hat{x}_{t-1} + B_t u_t\]&lt;/span&gt;&lt;br /&gt;&#10;先验误差协方差：&lt;br /&gt;&#10;&lt;span class="math display"&gt;\[P_t^{-} = F_t P_{t-1} F_t^T + Q_t\]&lt;/span&gt;&lt;br /&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;更新步骤&lt;/strong&gt;：&lt;br /&gt;&#10;卡尔曼增益：&lt;br /&gt;&#10;&lt;span class="math display"&gt;\[K_t = P_t^{-} H_t^T (H_t P_t^{-} H_t^T + R_t)^{-1}\]&lt;/span&gt;&lt;br /&gt;&#10;后验状态估计：&lt;br /&gt;&#10;&lt;span class="math display"&gt;\[\hat{x}_t = \hat{x}_t^{-} + K_t (z_t - H_t \hat{x}_t^{-})\]&lt;/span&gt;&lt;br /&gt;&#10;后验误差协方差：&lt;br /&gt;&#10;&lt;span class="math display"&gt;\[P_t = (I - K_t H_t) P_t^{-}\]&lt;/span&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/div&gt;&#10;&lt;div id="在计算贝塔时的应用" class="section level2"&gt;&#10;&lt;h2&gt;在计算贝塔时的应用&lt;/h2&gt;&#10;&lt;p&gt;在时变贝塔估计中，我们将CAPM模型置于状态空间框架下。假设在时刻&lt;span class="math inline"&gt;\(t\)&lt;/span&gt;，资产超额收益&lt;span class="math inline"&gt;\(r_{a,t}\)&lt;/span&gt;与市场超额收益&lt;span class="math inline"&gt;\(r_{m,t}\)&lt;/span&gt;满足：&lt;br /&gt;&#10;&lt;span class="math display"&gt;\[r_{a,t} = \alpha_t + \beta_t r_{m,t} + \epsilon_t\]&lt;/span&gt;&lt;br /&gt;&#10;其中，&lt;span class="math inline"&gt;\(\alpha_t\)&lt;/span&gt;和&lt;span class="math inline"&gt;\(\beta_t\)&lt;/span&gt;为时变参数，&lt;span class="math inline"&gt;\(\epsilon_t\)&lt;/span&gt;为观测噪声。&lt;/p&gt;&#10;&lt;p&gt;定义状态向量为&lt;span class="math inline"&gt;\(x_t = [\alpha_t, \beta_t]^T\)&lt;/span&gt;，则状态空间模型可表示为：&lt;br /&gt;&#10;- 状态方程（假设参数遵循随机游走）：&lt;br /&gt;&#10;&lt;span class="math display"&gt;\[x_t = x_{t-1} + w_t\]&lt;/span&gt;&lt;br /&gt;&#10;其中，&lt;span class="math inline"&gt;\(w_t\)&lt;/span&gt;为过程噪声，协方差矩阵为&lt;span class="math inline"&gt;\(Q\)&lt;/span&gt;。&lt;br /&gt;&#10;- 观测方程：&lt;br /&gt;&#10;&lt;span class="math display"&gt;\[z_t = H_t x_t + v_t\]&lt;/span&gt;&lt;br /&gt;&#10;其中，&lt;span class="math inline"&gt;\(z_t = r_{a,t}\)&lt;/span&gt;，&lt;span class="math inline"&gt;\(H_t = [1, r_{m,t}]\)&lt;/span&gt;，&lt;span class="math inline"&gt;\(v_t = \epsilon_t\)&lt;/span&gt;为观测噪声，方差为&lt;span class="math inline"&gt;\(R\)&lt;/span&gt;。&lt;/p&gt;&#10;&lt;p&gt;通过卡尔曼滤波递归处理数据，可得到状态向量（即&lt;span class="math inline"&gt;\(\alpha_t\)&lt;/span&gt;和&lt;span class="math inline"&gt;\(\beta_t\)&lt;/span&gt;）的最优估计。滤波结果（Filtered）基于当前及过去信息，适用于实时估计；平滑结果（Smoothed）利用全部样本信息，适用于事后分析。&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="r代码实例" class="section level1"&gt;&#10;&lt;h1&gt;R代码实例&lt;/h1&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# 安装必要的包（如果尚未安装）&#10;if (!require(&amp;quot;quantmod&amp;quot;)) install.packages(&amp;quot;quantmod&amp;quot;) # 用于获取数据&#10;if (!require(&amp;quot;dlm&amp;quot;)) install.packages(&amp;quot;dlm&amp;quot;) # 用于卡尔曼滤波&#10;if (!require(&amp;quot;ggplot2&amp;quot;)) install.packages(&amp;quot;ggplot2&amp;quot;) # 用于绘图&#10;if (!require(&amp;quot;reshape2&amp;quot;)) install.packages(&amp;quot;reshape2&amp;quot;) # 用于数据重塑&#10;&#10;# 加载包&#10;library(quantmod)&#10;library(dlm)&#10;library(ggplot2)&#10;library(reshape2)&#10;&#10;# 设置时间范围&#10;start_date &amp;lt;- as.Date(&amp;quot;2020-01-01&amp;quot;)&#10;end_date &amp;lt;- Sys.Date() # 使用当前日期&#10;&#10;# 下载AAPL和SPY的日收盘价数据&#10;getSymbols(&amp;quot;AAPL&amp;quot;, src = &amp;quot;yahoo&amp;quot;, from = start_date, to = end_date)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;AAPL&amp;quot;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;getSymbols(&amp;quot;SPY&amp;quot;, src = &amp;quot;yahoo&amp;quot;, from = start_date, to = end_date)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;SPY&amp;quot;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# 提取收盘价并合并数据&#10;aapl_close &amp;lt;- Cl(AAPL)&#10;spy_close &amp;lt;- Cl(SPY)&#10;merged_data &amp;lt;- merge(aapl_close, spy_close)&#10;colnames(merged_data) &amp;lt;- c(&amp;quot;AAPL&amp;quot;, &amp;quot;SPY&amp;quot;)&#10;&#10;# 计算日对数收益率&#10;returns &amp;lt;- na.omit(data.frame(&#10; Date = index(merged_data),&#10; AAPL_Return = as.numeric(ROC(merged_data$AAPL)),&#10; SPY_Return = as.numeric(ROC(merged_data$SPY))&#10;))&#10;&#10;# 使用dlm构建卡尔曼滤波模型&#10;buildCapm &amp;lt;- function(parm) {&#10; dlmMod &amp;lt;- dlm(&#10; FF = matrix(c(1, 0), nrow=1),&#10; V = exp(parm[1]),&#10; GG = diag(2),&#10; W = diag(exp(parm[2:3])),&#10; m0 = c(0, 1),&#10; C0 = diag(2)&#10; )&#10; dlmMod$JFF &amp;lt;- matrix(c(0, 1), nrow=1)&#10; dlmMod$X &amp;lt;- returns$SPY_Return&#10; return(dlmMod)&#10;}&#10;&#10;# 初始参数猜测（取对数后的方差）&#10;init_parm &amp;lt;- c(log(0.01), log(0.0001), log(0.0001))&#10;&#10;# 使用dlmMLE优化参数&#10;mle_result &amp;lt;- dlmMLE(&#10; y = returns$AAPL_Return,&#10; parm = init_parm,&#10; build = buildCapm&#10;)&#10;&#10;# 检查优化是否成功&#10;if (mle_result$convergence != 0) {&#10; warning(&amp;quot;参数优化可能未完全收敛。&amp;quot;)&#10;}&#10;&#10;# 用优化后的参数构建最终的dlm模型&#10;final_model &amp;lt;- buildCapm(mle_result$par)&#10;&#10;# 运行卡尔曼滤波和平滑&#10;filtered_result &amp;lt;- dlmFilter(returns$AAPL_Return, final_model)&#10;smoothed_result &amp;lt;- dlmSmooth(filtered_result)&#10;&#10;# 提取平滑后的状态估计&#10;alpha_smoothed &amp;lt;- smoothed_result$s[-1, 1]&#10;beta_smoothed &amp;lt;- smoothed_result$s[-1, 2]&#10;&#10;# 提取滤波后的状态估计&#10;alpha_filtered &amp;lt;- filtered_result$m[-1, 1]&#10;beta_filtered &amp;lt;- filtered_result$m[-1, 2]&#10;&#10;# 将结果添加到数据框中&#10;returns$Alpha_Smoothed &amp;lt;- alpha_smoothed&#10;returns$Beta_Smoothed &amp;lt;- beta_smoothed&#10;returns$Alpha_Filtered &amp;lt;- alpha_filtered&#10;returns$Beta_Filtered &amp;lt;- beta_filtered&#10;&#10;# 绘制时变贝塔系数&#10;ggplot(returns, aes(x = Date)) +&#10; geom_line(aes(y = Beta_Smoothed, color = &amp;quot;Smoothed β&amp;quot;), linewidth = 0.8) +&#10; geom_line(aes(y = Beta_Filtered, color = &amp;quot;Filtered β&amp;quot;), linewidth = 0.5, linetype = &amp;quot;dashed&amp;quot;, alpha = 0.7) +&#10; geom_hline(yintercept = 1, linetype = &amp;quot;dotted&amp;quot;, color = &amp;quot;black&amp;quot;) +&#10; labs(title = &amp;quot;AAPL vs SPY: Dynamic Beta Coefficient (Kalman Filter)&amp;quot;,&#10; x = &amp;quot;Date&amp;quot;,&#10; y = &amp;quot;Beta Value&amp;quot;,&#10; color = &amp;quot;Estimation Type&amp;quot;) +&#10; theme_bw() +&#10; scale_color_manual(values = c(&amp;quot;Smoothed β&amp;quot; = &amp;quot;darkgreen&amp;quot;, &amp;quot;Filtered β&amp;quot; = &amp;quot;darkred&amp;quot;))&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;&lt;img src="https://gewutang.cn/2025/08/23/kalman-beta/index_files/figure-html/unnamed-chunk-1-1.png" width="672" /&gt;&lt;/p&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# 绘制时变阿尔法系数&#10;ggplot(returns, aes(x = Date)) +&#10; geom_line(aes(y = Alpha_Smoothed, color = &amp;quot;Smoothed α&amp;quot;), linewidth = 0.8) +&#10; geom_hline(yintercept = 0, linetype = &amp;quot;dotted&amp;quot;, color = &amp;quot;black&amp;quot;) +&#10; labs(title = &amp;quot;AAPL vs SPY: Dynamic Alpha Coefficient (Kalman Filter)&amp;quot;,&#10; x = &amp;quot;Date&amp;quot;,&#10; y = &amp;quot;Alpha Value&amp;quot;,&#10; color = &amp;quot;Estimation Type&amp;quot;) +&#10; theme_bw() +&#10; scale_color_manual(values = c(&amp;quot;Smoothed α&amp;quot; = &amp;quot;darkgreen&amp;quot;))&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;&lt;img src="https://gewutang.cn/2025/08/23/kalman-beta/index_files/figure-html/unnamed-chunk-1-2.png" width="672" /&gt;&lt;/p&gt;&#10;&lt;/div&gt;&#10;</description></item><item><title>Rattle:R中的数据挖掘GUI第4章试读</title><link>https://gewutang.cn/2014/04/16/rattle-chap-4/</link><pubDate>Wed, 16 Apr 2014 00:00:00 +0000</pubDate><guid>https://gewutang.cn/2014/04/16/rattle-chap-4/</guid><description>&lt;h2 id="第四章-导入数据"&gt;&lt;a href="#%e7%ac%ac%e5%9b%9b%e7%ab%a0-%e5%af%bc%e5%85%a5%e6%95%b0%e6%8d%ae" class="header-anchor"&gt;&lt;/a&gt;第四章 导入数据&#10;&lt;/h2&gt;&lt;p&gt;数据具有不同的来源和格式。借助R软件的高扩展性能，Rattle提供了与各种格式数据源的接口。能与使用R软件实属幸运，因为R系统属开源系统，因而，可以非常方便地与其它应用进行协作通信。R语言支持多种数据格式的直接导入。&lt;/p&gt;&#10;&lt;p&gt;不同软件之间最常用的数据通信格式是逗号分隔文件（CSV）。这些文件的扩展名是.csv。这是一种面向行列的简单文本格式，其中各列以逗号隔开。这类文件可以用来在电子表格、数据库、气象观测站以及其它应用之间进行数据导入和导出。如果对列分隔符稍作改变，比如替换为制表符，就得到通常以txt为扩展名的文本文件。&lt;/p&gt;&#10;&lt;p&gt;这些简单的数据格式（csv和txt文件）未包括元数据信息。这意味着文件中对文件中所包含的数据的结构进行描述的信息。当其它软件读入此类数据时，需要对此进行假设。&lt;/p&gt;&#10;&lt;p&gt;其它类型的数据源提供了描述数据的信息，因而，我们的软件读入这类数据时不需要猜测其读入的内容。属性关联文件格式（4.2节）通常以.arff为扩展名，它在csv格式的基础上增加了元数据。&lt;/p&gt;&#10;&lt;p&gt;从数据库中直接提取的数据通常会提供元数据信息。开放数据库互联（ODBC）标准提供了一个从多种数据库中获取数据的开放式接口，而R软件对此提供了相应的支持。这允许我们与多种数据源包括Microsoft excel,microsoft access ,SQL server Oracle MySQL,Postgre以及SQLite进行直接通信。4.3节会介绍 RODBC。&lt;/p&gt;&#10;&lt;p&gt;没有必要在 Rattle 中提供在R中载入数据的所有功能。然而，我们可以用底层的R命令字载入数据，并在Rattle中进行检索，这部分内容详见4.4节。&lt;/p&gt;&#10;&lt;p&gt;R包本身也是提供了丰富的数据集。虽然许多数据集可能跟我们选定的主题无关，但我们可以借助他们来体验R中的数据挖掘过程。通过 rattle 界面的library 按钮或者 data 菜单下的 soource 可以查看到包含在当前库中的数据集列表。这部分内容详见&#10;4.6节。&lt;/p&gt;&#10;&lt;p&gt;通过相关机制将数据载入rattle之后，我们需要定义数据集中各个变量的角色，同时，需要设定数据集中各条观测值在数据挖掘过程中的使用方式。这些信息会记录在rattle界面上，而rattle本身也提供了诸多有用的默认设置。&lt;/p&gt;&#10;&lt;p&gt;选定数据集，并执行 Data 菜单之后，将看到针对数据的文本性描述。&#10;图4.1显示的是载入 weather.csv 文件之后的Rattle应用界面，weather.csv 是 rattle 包自带的一个样例数据集。打开R软件，载入 rattle包 ，启动 rattle 应用，再点击 Execute 按钮请求加载 weather 数据集即可得到上述结果：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;library(rattle)&#10;rattle()&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;图4.1 载入 weather.csv 数据集&lt;/p&gt;&#10;&lt;p&gt;本章将概述各种源数据格式并讨论如何导入它们以进行数据挖掘。此外，还将讨论 Rattle 提供的关于数据挖掘过程中如何使用数据的设定。&lt;/p&gt;&#10;&lt;h3 id="41-csv-数据"&gt;&lt;a href="#41-csv-%e6%95%b0%e6%8d%ae" class="header-anchor"&gt;&lt;/a&gt;4.1 CSV 数据&#10;&lt;/h3&gt;&lt;p&gt;最简单、最常用的一种数据交换格式是逗号分隔文件（CSV）格式。这种格式的文件已日渐成为在不同软件应用中交换数据的标准格式。其以 CSV 为扩展名，可以在电子表格、数据库包括 LibreOffice ，Calc ,Gnumeric,Microsoft Excel，SAS/Enterprise Miner,Teradata,Netezza 和其它软件应用中导入和导出。基于此，CSV 格式非常适宜用来向 rattle 中导入数据。这种数据文件的缺点是没有包含显式的元数据信息（元数据，又叫数据的数据，包括数据文件中的数据类型是数值型还是分类型等信息）。由于缺失元数据信息，R 软件有时候会搞错数据中某特定列的数据类型。不过，问题不大，在使用R载入数据时，我们可以帮助其识别数据类型信息。&lt;/p&gt;&#10;&lt;h4 id="数据定位和数据载入"&gt;&lt;a href="#%e6%95%b0%e6%8d%ae%e5%ae%9a%e4%bd%8d%e5%92%8c%e6%95%b0%e6%8d%ae%e8%bd%bd%e5%85%a5" class="header-anchor"&gt;&lt;/a&gt;数据定位和数据载入&#10;&lt;/h4&gt;&lt;p&gt;通过Data菜单下的 Speadsheet 选项，可以直接导入 CSV 数据。点击 Filename 按钮(图4.2)会看到文件选择对话框（图4.3）。浏览到要载入的CSV文件，选中之后点击 Open 按钮。&lt;/p&gt;&#10;&lt;p&gt;图4.2 Data菜单的SpreadSheet选项，对文件名字进行了高亮。点击该按钮可以打开文件选择器&lt;/p&gt;&#10;&lt;p&gt;现在要做的是将数据载入到 rattle 中。通常，我们通过点击 Execute 按钮（也可以点F2）来完成这一过程。这一操作会将文件内容从硬盘读入到计算机的内存里，然后，可以作为 Rattle中的数据集来使用了。&lt;/p&gt;&#10;&lt;p&gt;Rattle提供来多个CSV格式的示例文件，其中包括weather.csv数据文件。在安装Rattle时，该文件已经同时安装。使用system.file()函数可以知道该文件的具体地址，在R控制台运行下面的命令：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;system.file(&amp;quot;csv&amp;quot;, &amp;quot;weather.csv&amp;quot;, package=&amp;quot;rattle&amp;quot;)&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;返回的地址信息取决于用户的操作系统以及R的安装方式。上面得到的地址是一个标准安装的Ubuntu GNU/Linux 系统的相对位置。&lt;/p&gt;&#10;&lt;p&gt;提示：在Rattle中点击两下鼠标（Execute和Yes）即可再次载入该文件。接着，点击Filename按钮（显示为weather.csv）一个文本浏览器，此时窗口的顶部显示的是文件地址。&lt;/p&gt;&#10;&lt;p&gt;我们可以用file.show()函数查看文件内容。这一操作会弹出一个显示文件内容的窗口：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;fn &amp;lt;- system.file(&amp;quot;csv&amp;quot;, &amp;quot;weather.csv&amp;quot;, package=&amp;quot;rattle&amp;quot;)&#10;file.show(fn)&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;撇开R和Rattle，我们可以用随便一个文本编辑器直接查看文件内容。对于不熟悉CSV类型文件的用户来说，这非常有用。我们可以看到文件的头部内容如下所示：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;Date,Location,MinTemp,MaxTemp,Rainfall,Evaporation...&#10;2007-11-01,Canberra,8,24.3,0,3.4,6.3,NW,30,SW,NW...&#10;2007-11-02,Canberra,14,26.9,3.6,4.4,9.7,ENE,39,E,W...&#10;2007-11-03,Canberra,13.7,23.4,3.6,5.8,3.3,NW,85,N,NNE...&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;图4.3CSV文件选择器只显示文件夹中扩展名为.csv的文件。通过选择右小角下拉式菜单，我们可以只显示扩展名为.txt（以制表符作为分隔符的文件常以此为扩展名）或者其他任意扩展名的文件。&lt;/p&gt;&#10;&lt;p&gt;CSV文件通常是一个在标题行列出所有变量名字，并以逗号作为分隔符的普通文本文件。可推想得知标题行后面的部分是按行排列的观测值记录。每条观测值内部以逗号作为分隔符，也即每个变量对应的观测值都以逗号进行分隔。&lt;/p&gt;&#10;&lt;p&gt;可以使用read.csv()函数将CSV文件载入到Rattle中。查看Log菜单中的内容可以了解操作过程。从Log菜单，我们可以看到下面的内容:&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;crs$dataset &amp;lt;- read.csv(&amp;quot;file:.../weather.csv&amp;quot;,na.strings=c(&amp;quot;.&amp;quot;, &amp;quot;NA&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;?&amp;quot;),strip.white=TRUE)&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;为了简化输出结果，这里省略来weather.csv文件对应的完整路径的部分内容。因而，复制黏贴来运行上述命令将会报错。一个替代做法是将Log菜单中对应的命令行复制到R控制台。&lt;/p&gt;&#10;&lt;p&gt;上述函数的执行结果是数据集本身被载入到内存中，并可以用crs$dataset对其加以引用。&lt;/p&gt;&#10;&lt;p&gt;函数的第二个参数（na.strings=）列出了四个字符串，如果变量的取值为其中之一，则其将被转化为R中的缺失值（NA）。里出的四个字符串涵盖了大多数用来表示缺失值的符号。比如，SAS用点（.）来表示缺失值，而R用特殊字符串“NA”来表示缺失值。其它软件以更简单的空字符表示缺失值，还有一些（包括机器学习软件C4.5）使用问号（“？”）表示缺失值。&lt;/p&gt;&#10;&lt;p&gt;我们也可能用到strip.white=参数，将该参数设定为TRUE,将删除文件中的空白（比如，空格和制表符等）。这会使源CSV文件的逗号对齐，从而便于人眼查看，同时能较好地支持缺失值。&lt;/p&gt;&#10;&lt;p&gt;使用read.csv()函数时不需要如此复杂。如果要将一个CSV文件载入R中（请用文件的实际路径替换代码中的&amp;hellip;）,运行下面的命令即可：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;ds &amp;lt;- read.csv(&amp;quot;.../weather.csv&amp;quot;)&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;也可以直接从互联网上载入数据。例如，可以从togaware.com上读取weather数据集：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;ds &amp;lt;- read.csv(&amp;quot;http://rattle.togaware.com/weather.csv&amp;quot;)&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;第2章中讲道，如果未通过Filename按钮指定其它数据文件，则Rattle会自动加载包中提供的是示例数据文件（weather.csv）。这是最简单的一种导入数据到Rattle中的方法，其对学习Rattle界面大有帮助。&lt;/p&gt;&#10;&lt;p&gt;选定要载入的文件之后，务必记得点击Excute按钮，这样才能真正将数据载入到Rattle。接下来，Data菜单的主文本面板会发生变化，列出所有的变量、对应的类型、其在建模过程中的角色以及其他有用信息，如图4.1所示。&lt;/p&gt;&#10;&lt;p&gt;将数据从文件导入到Rattle之后，会创建一个数据集，接下来我们就可以探索数据了。第2章曾讲到，我们可以在控制台中查看文件头部的内容。下面我们只显示数据集的前五个变量以及前六个观测值：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;head(crs$dataset[1:5], 6)&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;Date Location MinTemp MaxTemp Rainfall&#10;1 2007-11-01 Canberra 8.0 24.3 0.0&#10;2 2007-11-02 Canberra 14.0 26.9 3.6&#10;3 2007-11-03 Canberra 13.7 23.4 3.6&#10;4 2007-11-04 Canberra 13.3 15.5 39.8&#10;5 2007-11-05 Canberra 7.6 16.1 2.8&#10;6 2007-11-06 Canberra 6.2 16.9 0.0&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;前文提及（2.9节），Rattle会将数据集保存在名为crs的环境里面，因此，在R中，我们可以直接用crs$dataset来引用该数据集。&lt;/p&gt;&#10;&lt;p&gt;在Rattle界面下，一旦载入数据集，就可以点击View按钮，以电子表格的形式来查看数据集。这一过程是通过调用RGtk2Extras包(Taverner等,2010)中的dfedit()函数来完成的。&lt;/p&gt;&#10;&lt;h4 id="数据格式微调"&gt;&lt;a href="#%e6%95%b0%e6%8d%ae%e6%a0%bc%e5%bc%8f%e5%be%ae%e8%b0%83" class="header-anchor"&gt;&lt;/a&gt;数据格式微调&#10;&lt;/h4&gt;&lt;p&gt;Rattle界面提供了很多调整读入CSV文件方式的选项。如图4.2所示，其中包括Separator和Header。&lt;/p&gt;&#10;&lt;p&gt;我们可以通过Separator的输入来选择字段分隔符。默认的分隔符是逗号。载入TXT文件时，由于其以制表符作为字段分隔符，因而，我们需要用表示制表符的专用码“\t”（在t前面加两个斜杠）来替换逗号。我们也可以令输入为空，此时，任意空白（比如，任意数量的空格或者制表符）将会视为分隔符。&lt;/p&gt;&#10;&lt;p&gt;从read.csv()函数的使用角度来说，输入分隔符的作用相当于在函数中包含适当的参数（使用sep=）。举个例子，比如，有一个以制表符作为分隔符的文件，名为“mydata.txt”，我们可以在函数中应用sep=：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;ds &amp;lt;- read.csv(&amp;quot;mydata.txt&amp;quot;,sep=&amp;quot;\t&amp;quot;)&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;提示：注意直接在R中指定制表符作为分隔符时使用的是一个斜杠，而不是像Rattle界面中的两个斜杠。&lt;/p&gt;&#10;&lt;p&gt;另外一个在载入数据时十分有用的选项是Header复选框。通常，CSV文件会将第一行作为列名。这些名字将被R和Rattle认为是变量名。然而，并非所有的CSV文件都包括标题。对于这样的文件，不要勾选Header复选框。载入不包含标题的CSV文件时，R会自动生成一些列名。复选框会将输入转化为read.csv()函数中的header=参数。将header=设定为FALSE，则文件的第一行会被视为数据而不是标题行。假设我们有一个叫“mydata.csv”的文件，读入该文件的read.csv()命令是：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;ds &amp;lt;- read.csv(&amp;quot;mydata.csv&amp;quot;,header=FALSE)&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;提示：数据中的每一行可以包含不同的列数，每一行的缺失列会从后面以NA补足。这是通过read.csv()函数中的fill=参数来完成的，该参数的默认值是TRUE。&lt;/p&gt;&#10;&lt;h4 id="基础数据描述"&gt;&lt;a href="#%e5%9f%ba%e7%a1%80%e6%95%b0%e6%8d%ae%e6%8f%8f%e8%bf%b0" class="header-anchor"&gt;&lt;/a&gt;基础数据描述&#10;&lt;/h4&gt;&lt;p&gt;数据集载入Rattle之后，我们就可以将从上面的基础描述中感知到数据的特征。例如，在图4.1中，第一个变量Datebei 视为每个观测值的序号。该变量共有366个不同的取值，这与观测值数目相同。&lt;/p&gt;&#10;&lt;p&gt;数据集中所有观测值对应的Location变量只有一个取值。因此，其被视为常数，且不参与建模过程。也即该变量会在建模过程中被忽略。&lt;/p&gt;&#10;&lt;p&gt;图4.1看到，接下来的5个变量被标记为数值型变量，接着是分类变量WindGustDir等等。Commnent列标示的是所有取值的数目以及每个变量对应的缺失值的数目。比如说，Sunshine变量共有114个不同的取值和3个缺失值。本书第7章将讨论缺失值的处理问题。&lt;/p&gt;&#10;&lt;h3 id="42-arff数据"&gt;&lt;a href="#42-arff%e6%95%b0%e6%8d%ae" class="header-anchor"&gt;&lt;/a&gt;4.2 ARFF数据&#10;&lt;/h3&gt;&lt;p&gt;属性关系文件格式是一种由CSV文件以及文件顶部的数行元数据组成的一种文本文件格式。ARFF格式的文件最初是为机器学习软件Weka（Witten和Frank，2005）设计的，有很多数据都发布为这种格式。在Rattle中，我们可以通过ARFF选项（图 4.4）载入ARFF格式的数据，需要指定包含数据的文件名。&lt;/p&gt;&#10;&lt;p&gt;Rattle包提供了ARFF的文件的示例。载入ARFF之前，先启动Rattle并加载weather数据之后（2.4节），选择ARFF选项并点击Filename选择器，范围上一级目录，进入arff文件夹，选择要加载的数据。&lt;/p&gt;&#10;&lt;p&gt;图4.4 选择ARFF单选按钮加载ARFF文件&lt;/p&gt;&#10;&lt;p&gt;CSV文件和ARFF文件最大的区别在于是否有文件头部的数据描述区。数据描述区包含了数据集中每个变量的信息。weather数据集对应的ARFF格式的文件如下所示。注意，在ARFF格式的文件中，变量被视为属性。&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;@relation weather&#10;@attribute Date date&#10;@attribute Location {Adelaide, Albany, ...}&#10;@attribute MinTemp numeric&#10;@attribute MaxTemp numeric&#10;...&#10;@attribute RainTomrrow {No, Yes}&#10;@data&#10;2010-11-01,Canberra,8,24.3,0,...,Yes&#10;2010-11-02,Canberra,14,26.9,3.6,...,Yes&#10;2010-11-03,Canberra,?,23.4,3.6,...,Yes&#10;...&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;数据描述区相当简单明了。以数据集的名字（用ARFF的术语，则是关系的名字）开头。接下来是描述每个观测值的变量名以及变量对应的数据类型。每一行对应一个变量定义（上例中省略了部分内容）。数值型变量被识别为数值型、实数型或者整形变量。对于分类数据，则列出了所有可能取值。另外两个能被ARFF识别的数据类型是字符串和日期。字符串类型的变量意味着其可以将字符串（或者文本序列）作为取值。而data数据类型可以指定日期的记录格式。默认格式遵循ISO-8601标准，型如&amp;quot;yyyy-MM-dd&amp;quot;‘T’HH:mm:ss&amp;quot;。&lt;/p&gt;&#10;&lt;p&gt;数据描述区下面是按行列示的具体观测值，以逗号作为分隔符，与CSV文件类似。&lt;/p&gt;&#10;&lt;p&gt;ARFF文件优于CSV数据文件的地方在于源数据信息。这一点对Rattle尤其有用，因为Rattle中分类数据的可能取值是由读入CSV文件时的数据决定的，所以，所有没有出现在数据中的分类变量的可能取值自然都丢掉了。当从ARFF文件中读入数据时，元数据会列出分类变量的所有可能取值，即使该取值在真是数据中并未出现。在第12章，探讨构建和部署随机森林模型时会专门讲到这个专题。&lt;/p&gt;&#10;&lt;p&gt;ARFF文件可以包括注释，注释行通常以“%”开头。包含的注释行能记录更多数据的额外信息，包括数据是如何得来的，来源是哪里以及如何引用数据等。&lt;/p&gt;&#10;&lt;p&gt;ARFF文件中的缺失值以记录为“？”。这可以被R中的read.arff()函数识别出来，我们将其视为跟Rattle中的NA相同。&lt;/p&gt;&#10;&lt;p&gt;综上，ARFF格式的文件，除了简单之外，与CSV相比有诸多优势。不过，CSV依旧是最常用的数据文件格式。&lt;/p&gt;&#10;&lt;h3 id="43-odbc源数据"&gt;&lt;a href="#43-odbc%e6%ba%90%e6%95%b0%e6%8d%ae" class="header-anchor"&gt;&lt;/a&gt;4.3 ODBC源数据&#10;&lt;/h3&gt;&lt;p&gt;许多数据被存储在数据库或者数据仓库里。开源数据库连接标准（ODBC）被界定为访问数据库（也包括数据仓库）中数据的常用方法。其以查询关系型数据的结构性查询语言（SQL）为基础。下面讨论如何直接访问这些数据库中的数据。使用Rattle的ODBC选项（如图4.5），Rattle可以借助ODBC直接获取任意数据库的数据集。在GUI的底层，实际上是RODBC（Ripley和Lapsley,2010）提供了R与ODBC数据源的接口。&lt;/p&gt;&#10;&lt;p&gt;图4.5 通过ODBC数据库连接载入数据&lt;/p&gt;&#10;&lt;p&gt;通过ODBC访问数据的关键在于通过数据源名字（或者DSN）来识别数据源，不同的系统提供了不同的设定DSNs的机制。例如，在GNU/Linux操作系统下，使用unixodbc应用，系统的DSNs通常定义在/etc/odbcinst.ini和/etc/odbc.ini中。在微软Windows下面，控制面板提供了管理ODBC数据源的工具。&lt;/p&gt;&#10;&lt;p&gt;在Rattle中，我们通过在DNS文本输入框中输入名字来设置DSN(图4.5)。一般DSN指定之后，Rattle就尝试去建立连接。许多ODBC驱动在建立连接之前会要求输入用户名和密码。图4.6演示来输入类似信息的弹窗，这个例子中连接的数据仓库是Netezza。&lt;/p&gt;&#10;&lt;p&gt;在R中运行RODBC中的dobcConnect()函数可以直接建立连接。该函数建立了一个连接远程数据源的通道：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;library(RODBC)&#10;channel &amp;lt;- odbcConnect(&amp;quot;myDWH&amp;quot;, uid=&amp;quot;kayon&amp;quot;, pwd=&amp;quot;toga&amp;quot;)&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;与数据源建立连接之后，Rattle会自动查询数据库中的表名，并通过如图4.5中的下拉列表Table来访问查询得到的表。我们需要选择要加载的表。&lt;/p&gt;&#10;&lt;p&gt;R中为数不多的对ODBC连接进行微调的选项可以被Rattle调用。其中一个选项允许我们对从选中表中检索得到的行数进行限定。如果将行数限制设定为0，则检索会返回整个表。不方便的地方在于没有标准的SQL标准来对查询返回的行数进行限定。一些数据库系统（比如，Teradata和Netezza）的SQL关键字是LIMIT，Rattle借用来这一关键字。&lt;/p&gt;&#10;&lt;p&gt;RODBC提供了一系列可与数据库进行交互的R函数。例如，sqlTables()函数可以返回所有可用表的名字。我们为其传递一个前面创建的通道来与数据库进行通信：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;tables &amp;lt;- sqlTables(channel)&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;如果查询连接的数据库中有个表叫clients，我们可用sqlColumns()函数得到该表的列名字段。&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;columns &amp;lt;- sqlColumns(channel, &amp;quot;clients&amp;quot;)&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;有时，我们只想从数据库中加载某个特定的子集。这时，可直接通过SQL查询语句检索出想要的数据。例如：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;query &amp;lt;- &amp;quot;SELECT * FROM clients WHERE cost &amp;gt; 2500&amp;quot;&#10;myds &amp;lt;- sqlQuery(channel, query)&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;直接使用R为精确识别要加载的数据提供了更多的操作空间。我们可以用任意的SQL查询来替代前面的SELECT语句。对于熟悉SQL查询的来说，这提供了一个强大的机制使我们能够在数据载入之前对数据进行重新定义。&lt;/p&gt;&#10;&lt;p&gt;像上文这样，通过向通道直接发送SQL查询载入数据时，得到的数据将被保存为R中的数据集，我们可以用myds（根据前文定义）引用该数据集。通过Rattle中的R Dataset选项可以访问该数据集，下节将对此进行介绍。&lt;/p&gt;&#10;&lt;h3 id="44-r数据集其他数据源"&gt;&lt;a href="#44-r%e6%95%b0%e6%8d%ae%e9%9b%86%e5%85%b6%e4%bb%96%e6%95%b0%e6%8d%ae%e6%ba%90" class="header-anchor"&gt;&lt;/a&gt;4.4 R数据集——其他数据源&#10;&lt;/h3&gt;&lt;p&gt;R可以以多种方式从多种数据源载入数据。前面已经介绍过从数据文件（CSV或者TXT文件）或者数据库直接载入数据的内容。然而，R还提供了更多从多种数据源导入数据的选项。&lt;/p&gt;&#10;&lt;p&gt;任何已经载入R中的数据集（技术上而言，是任意数据框）都可以作为Rattle进行数据挖掘的对象。选定Data菜单的R Dataset选项之后（图4.7），Data Name下拉菜单中会列出所有能被载入Rattle作为数据集的数据框名。&lt;/p&gt;&#10;&lt;p&gt;借助foreign包（DebRoy和Bivand,2011）,可以直接将SPSS格式数据集（read.spss）、SAS XPORT格式数据集（read.xport()）和DBF数据库文件（read.dbf()）。要指出的是，SAS专属数据格式作为例外不能直接载入到R中，除非我们有SAS的许可，允许读入数据才行。&lt;/p&gt;&#10;&lt;h4 id="载入-spss-格式的数据集"&gt;&lt;a href="#%e8%bd%bd%e5%85%a5-spss-%e6%a0%bc%e5%bc%8f%e7%9a%84%e6%95%b0%e6%8d%ae%e9%9b%86" class="header-anchor"&gt;&lt;/a&gt;载入 SPSS 格式的数据集&#10;&lt;/h4&gt;&lt;p&gt;举个例子，假设我们有一个从SPSS保存或者导出的数据文件。我们可以运行read.spss()函数导入数据：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;library(foreign)&#10;mydataset &amp;lt;- read.spss(&amp;quot;file=mydataset.sav&amp;quot;)&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;然后，如图4.7所示，我们看到数据框名mydataset，已经作为可用数据集出现在了R Dataset的下拉列表中。&lt;/p&gt;&#10;&lt;p&gt;图4.7 载入一个定义好的数据框作为Rattle可用的数据集&lt;/p&gt;&#10;&lt;p&gt;必须将供Rattle使用的数据集加载或者创建到运行Rattle的R会话（即我们加载了rattle包的那个R控制台）中才行。&lt;/p&gt;&#10;&lt;h4 id="从剪贴板读入数据"&gt;&lt;a href="#%e4%bb%8e%e5%89%aa%e8%b4%b4%e6%9d%bf%e8%af%bb%e5%85%a5%e6%95%b0%e6%8d%ae" class="header-anchor"&gt;&lt;/a&gt;从剪贴板读入数据&#10;&lt;/h4&gt;&lt;p&gt;图4.8 选中电子表格的部分区域并复制到剪贴板&lt;/p&gt;&#10;&lt;p&gt;一个有时用起来很方便的有趣做法是，R可以通过系统剪贴板对数据进行复制和剪贴。通过这一机制，我们可以把数据从电子表格复制（跟通常的复制黏贴类似）到剪贴板上。然后，在R中，使用read.table()函数将数据“黏贴”到一个数据集中。&lt;/p&gt;&#10;&lt;p&gt;假设我们打开了一个如图4.8所示的电子表格。按常规做法，选取16行数据，包括表头，运行下述命令可将数据载入到R里：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;expenses &amp;lt;- read.table(file(&amp;quot;clipboard&amp;quot;),header=TRUE)&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;接下来，就可以在Rattle中使用expenses数据框了。&lt;/p&gt;&#10;&lt;h4 id="日期转换"&gt;&lt;a href="#%e6%97%a5%e6%9c%9f%e8%bd%ac%e6%8d%a2" class="header-anchor"&gt;&lt;/a&gt;日期转换&#10;&lt;/h4&gt;&lt;p&gt;默认情况下，上例中的Date变量在加载时被视为分类变量。在将其载入Rattle时，运行下面的命令，可以将其转化为日期类型，如图4.9所示：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;expenses$Date &amp;lt;- as.Date(expenses$Date,&#10;format=&amp;quot;%d-%b-%Y&amp;quot;)&#10;head(expenses)&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;Date Expense Total&#10;1 2005-11-17 19.5 19.5&#10;2 2005-11-23 -15.0 4.5&#10;3 2005-12-10 30.0 34.5&#10;4 2006-01-23 -110.0 -75.5&#10;5 2006-01-28 -20.0 -95.5&#10;6 2006-02-14 -10.0 -105.5&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;图4.9 通过剪贴板的复制、黏贴操作从电子表格中载入数据框&lt;/p&gt;&#10;&lt;h4 id="直接从万维网读取数据"&gt;&lt;a href="#%e7%9b%b4%e6%8e%a5%e4%bb%8e%e4%b8%87%e7%bb%b4%e7%bd%91%e8%af%bb%e5%8f%96%e6%95%b0%e6%8d%ae" class="header-anchor"&gt;&lt;/a&gt;直接从万维网读取数据&#10;&lt;/h4&gt;&lt;p&gt;当今的很多数据都以万维网上的HTML格式提供。XML包（Lang,2011）提供了一系列直接从网上向R中导入数据的函数，然后，我们即可用Rattle（当然，也可以用R）对这些数据进行分析来。例如，我们读取谷歌列出的访问次数最多的网站列表数据，将其转化为数据框，以供Rattle使用。我们首先要载入XML包，并设定一些相关路径：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;library(XML)&#10;google &amp;lt;- &amp;quot;http://www.google.com/&amp;quot;&#10;path &amp;lt;- &amp;quot;adplanner/static/top1000/&amp;quot;&#10;top1000urls &amp;lt;- paste(google, path, sep=&amp;quot;&amp;quot;)&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;接下来可以用readHTMLTable()函数来读入数据，并提取相关表格、设定表格列名：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;tables &amp;lt;- readHTMLTable(top1000urls)&#10;top1000 &amp;lt;- tables[[2]]&#10;colnames(top1000) &amp;lt;- c('Rank', 'Site', 'Category',&#10;'Users', 'Reach', 'Views',&#10;'Advertising')&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;运行head()函数可以查看表格上的前几行数据：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;head(top1000)&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;Rank Site Category&#10;1 1 facebook.com Social Networks&#10;2 2 youtube.com Online Video&#10;3 3 yahoo.com Web Portals&#10;4 4 live.com Search Engines&#10;5 5 wikipedia.org Dictionaries &amp;amp; Encyclopedias&#10;6 6 msn.com Web Portals&#10;Users Reach Views Advertising&#10;1 880,000,000 47.2% 910,000,000,000 Yes&#10;2 800,000,000 42.7% 100,000,000,000 Yes&#10;3 660,000,000 35.3% 77,000,000,000 Yes&#10;4 550,000,000 29.3% 36,000,000,000 Yes&#10;5 490,000,000 26.2% 7,000,000,000 No&#10;6 450,000,000 24% 15,000,000,000 Yes&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h3 id="45-r数据"&gt;&lt;a href="#45-r%e6%95%b0%e6%8d%ae" class="header-anchor"&gt;&lt;/a&gt;4.5 R数据&#10;&lt;/h3&gt;&lt;p&gt;通过RData File选项（如图4.10），可以直接从本地的二进制R数据文件（扩展名通常是RData）中载入数据。这类文件通常包括多个数据集（以压缩格式保存），且常常是从先前的R会话中保存得到（使用save()函数）。&lt;/p&gt;&#10;&lt;p&gt;载入RData之前要先识别包含数据的文件。数据文件识别完成，数据集即被载入，然后，我们需要选择其中一个可用数据框作为Rattle中的数据集载入。这一步是通过Data Name下拉列表来指定，完成后点击Execute按钮即可在Rattle调用相应的数据集了。&lt;/p&gt;&#10;&lt;p&gt;图4.10 从二进制R文件中载入数据集&lt;/p&gt;&#10;&lt;p&gt;图4.10演示了选择RData文件的过程。图中可见，该文件的名字是cardiac.RData。数据文件识别完成后，Rattle会在Data Name下拉列表中列示文件中查询到的所有可用的数据框名。我们可以从数据文件中选择risk数据集载入Rattle。&lt;/p&gt;&#10;&lt;h3 id="46-库"&gt;&lt;a href="#46-%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;4.6 库&#10;&lt;/h3&gt;&lt;p&gt;几乎所有的R包都附带有帮助演示函数功能的示例数据集。我们已经看到Rattle包含数据集包括weather,weatherAUS和audit数据集。我们可以探索那些已经安装在R库中的R包的数据集。&lt;/p&gt;&#10;&lt;p&gt;Data菜单的Library允许我们调用这为数众多的示例数据集。点击单选框将看到一个所有可用数据集的列表，可以通过Data name下拉列表对其进行访问。下拉列表中包含了数据集名字、对应的包以及针对数据集的简要描述。注意，这个下拉列表可能很长，具体长度取决于已安装的R包的个数。我们看个例子，演示下Rattle用来生成上述列表的R代码：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;da &amp;lt;- data(package=.packages(all.available=TRUE))&#10;sort(paste(da$results[, &amp;quot;Item&amp;quot;], &amp;quot; : &amp;quot;,da$results[, &amp;quot;Package&amp;quot;], &amp;quot; : &amp;quot;,da$results[, &amp;quot;Title&amp;quot;], sep=&amp;quot;&amp;quot;))&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;...&#10;[10] &amp;quot;Adult : arules : Adult Data Set&amp;quot;&#10;...&#10;[12] &amp;quot;Affairs : AER : Fair's Extramarital Affairs Data&amp;quot;&#10;...&#10;[14] &amp;quot;Aids2 : MASS : Australian AIDS Survival Data&amp;quot;&#10;...&#10;[19] &amp;quot;airmay : robustbase : Air Quality Data&amp;quot;&#10;...&#10;[23] &amp;quot;ais : DAAG : Australian athletes data set&amp;quot;&#10;...&#10;[66] &amp;quot;audit : rattle : Sample dataset for data mining&amp;quot;&#10;...&#10;[74] &amp;quot;Baseball : vcd : Baseball Data&amp;quot;&#10;...&#10;[1082] &amp;quot;weather : rattle : Sample dataset for ...&amp;quot;&#10;...&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;在访问特定包的数据集之前，必须先用library()函数载入该包（Rattle里面会自动载入）。对于大多数R包（尤其是声明数据集延迟加载的R包，延迟加载意味着被引用时即被加载）而言，只需在R控制台键入相应的数据集名字即可调用数据。否则的话，访问数据之前要先用运行data()函数才行。我们需要为data()函数输入要加载的数据集名字。Rattle会自动处理这一过程，它会选择合适的操作来保证数据集可被访问。&lt;/p&gt;&#10;&lt;h3 id="47-数据选项"&gt;&lt;a href="#47-%e6%95%b0%e6%8d%ae%e9%80%89%e9%a1%b9" class="header-anchor"&gt;&lt;/a&gt;4.7 数据选项&#10;&lt;/h3&gt;&lt;p&gt;前文提及的Rattle中所有载入数据的选项，在载入数据集之后，会共享一系列选项。这些附加选项跟数据抽样以及分派变量的角色有关。下面从数据挖掘角度对此予以介绍。&lt;/p&gt;&#10;&lt;h4 id="数据分割"&gt;&lt;a href="#%e6%95%b0%e6%8d%ae%e5%88%86%e5%89%b2" class="header-anchor"&gt;&lt;/a&gt;数据分割&#10;&lt;/h4&gt;&lt;p&gt;2.7节提及，Partition选项允许我们将数据集分割为训练集、交叉验证集和测试集。3.1节进一步定义了数据分割的概念。这些概念面向的是预测性数据挖掘。一般来说，我们会基于训练集来构建模型。&lt;/p&gt;&#10;&lt;p&gt;可用对评估数据集应用模型来评估模型的优劣（第15章）。构建模式时，没有用到评估数据集，因此评估数据集可以对模型针对新观测时的优劣提供一个大致的估计。基于评估结果，我们可以对模型参数进行调试以寻求改进模型性能。&lt;/p&gt;&#10;&lt;p&gt;一旦模型结果令人满意，或者从交叉数据集的评估结果来看效果良好的话，就可以用第三部分数据即测试集来对模型进行评估了。由于在此之前，模型从未用到测试集中的观测值。因此，测试集得出的模型性能可以较好的预示，一旦能够得到新的观测值，该模型针对新观测值时的表现。&lt;/p&gt;&#10;&lt;p&gt;数据分割和抽样的概念，不仅仅是一种针对预测性数据挖掘来分割数据的机制。统计学家将抽样拓展为一种基于小数据集进行分析，从而推断出有关总体结论的学问。统计领域有众多知识，来保证我们对围绕着数据分析所得结论的不确定性的正确认知。这种认识十分重要，但数据挖掘过程中并为突出这一点。&lt;/p&gt;&#10;&lt;p&gt;Rattle使用sample()函数来生成随机分割或者抽样。随机样本通常能以较大的几率来反应总体的分布。因此，将大数据集抽样为小数据集之后，再用第5章中的方法来探索数据会更容易。探索10000个观测值比探索1000000个观测时更具交互性和实用性。抽样的其他优点还包括可以对不同的样本进行分析和绘图，以测量结果的稳定性和统计精确度。模型构建，尤其是随机森林模型的构建（第12章），将受益于此。&lt;/p&gt;&#10;&lt;p&gt;当数据挖掘的可得数据量较为庞大，构建模型将耗费大量时间（数小时甚至数日）时，这种抽样方法也非常必要。将数据集抽样为较小的数据集，能让我们在构建模型时具有更多的互动可能。一旦从最初的互动建模中找出清洗数据和转换数据的方法，就可以着手实验模型了。得到基础模型参数后，就需要对更大规模的数据进行清洗、转换和建模。在模型计算的数小时里，我们可以暂停监督了。&lt;/p&gt;&#10;&lt;p&gt;抽样的缺点，尤其是数据挖掘过程中的抽样缺点在于小概率事件可能没有包含在抽出的样本里。稀有疾病的案例，在大量的电子资金转账过程中形成的少数坏账，也有可能缺失，但它们却是我们在数据挖掘过程中感兴趣的项目。这种问题称之为类平衡问题。&lt;/p&gt;&#10;&lt;p&gt;默认情况下，Rattle提供的随机分割会将数据集的70%作为训练集，15%作为交叉验证集，15%作为测试集（图4.11）。我们可以根据需要对该比例进行调整。对大数据进行一些探索性分析时会用到抽样。使用计算量比较大的模型（比如，支持向量机）对数据建模时也会用到抽样。&lt;/p&gt;&#10;&lt;p&gt;图4.11 对weather数据集进行抽样&lt;/p&gt;&#10;&lt;p&gt;抽样还是会用到随机数。任何随机数在生成之前都需要设定随机种子。使用相同的随机种子，将得到相同的随机数，从而使相关过程可重复。通过修改随机种子，可以选择不同的随机数，当我们需要测试模型对不同抽样数据的敏感度时这会非常有用。&lt;/p&gt;&#10;&lt;p&gt;Rattle中常用一个默认的随机种子，这使得建模过程可重复。该随机种子将传递给R中的set.seed()函数，并称为生成下一个随机数序列的种子。因此，如果每次都将随机种子设定为同一个数字，就能保证我们得到相同的随机数。&lt;/p&gt;&#10;&lt;p&gt;当情形相反时，我们会想在建模过程中将随机种子设定为不同的数字，并依此评估每个模型的表现。我们针对原数据集的不同随机抽样构建模型。如果不同模型显著不相同的话，我们就需要斟酌我们建模方法的稳健性了。我们将在第15章进一步讨论此内容。&lt;/p&gt;&#10;&lt;h4 id="变量在模型中的角色"&gt;&lt;a href="#%e5%8f%98%e9%87%8f%e5%9c%a8%e6%a8%a1%e5%9e%8b%e4%b8%ad%e7%9a%84%e8%a7%92%e8%89%b2" class="header-anchor"&gt;&lt;/a&gt;变量在模型中的角色&#10;&lt;/h4&gt;&lt;p&gt;构建模型时，每个变量都将扮演特定的角色。大多数变量会作为模型的输入，而其中一个变量将作为建模的目标变量。有些变量也会作为风险变因（risk variable）。风险变因在建模过程中不会用到。通常用来记录与风险或者输出相关的重要性程度。例如，在audit数据集中，记录的是以美元计价的会计调整值。衡量的是与该案例相关的风险大小。在weather数据集中，风险变因是第二天的降雨量——降雨量可视为风险的大小。15.4节有一个在Rattle中使用风险变量的例子，针对的是模型评估过程。&lt;/p&gt;&#10;&lt;p&gt;最后，也可以将一些变量标记为建模时候的可忽略变量。&lt;/p&gt;&#10;&lt;p&gt;在向Rattle载入数据时，我们需要确保每个变量在建模过程中扮演合适的角色。大部分变量的默认角色是输入变量。通俗来说，这些变量是用来预测目标变量的变量。&lt;/p&gt;&#10;&lt;p&gt;目标变量，如果数据集中有相关的目标变量的话，通常是预测性建模过程中令我们感兴趣的变量。也即，它是记录历史数据输出结果的变量。在weather数据集中，目标变量是RainTomrrow，数据集audit的目标变量时Adjusted。&lt;/p&gt;&#10;&lt;p&gt;Rattle使用简单的经验法则来确定一个变量是否作为目标变量。基本的经验法则是:取值较少（低于5个）的变量会被视为候选目标变量。因为很多公开数据集的最后一个变量通常是目标变量，因而，数据集的最后一个变量常常被视为候选目标变量。如果最后一个变量的取值大于5，Rattle将从第一个变量开始，顺序查找到取值低于5的变量，前提是存在这样的变量。只有标记一个变量为目标变量。&lt;/p&gt;&#10;&lt;p&gt;同时，只有一个取值的整数变量常被自动视为标记变量（Ident）。可以标记任意数量的变量作为标记变量。所有的标记变量在建模过程中都会被忽略。但在对数据集进行排序时会用到，当结果被输出到排序文件中时，可以通过标记变量识别观测值。&lt;/p&gt;&#10;&lt;p&gt;在针对特定任务建模时，并非所有变量都会被用到。可以用单选按钮Ignore来忽略这些变量。&lt;/p&gt;&#10;&lt;p&gt;向Rattle载入数据时，特定的特殊字符串会用来识别变量角色。例如，名字以ID开头的变量会被自动标记为标记变量。用户可以对此进行调整。&lt;/p&gt;&#10;&lt;p&gt;与此类似，名义以IGNOGE开头的变量将设定为忽略变量。RISK和TARGET的情形也与此类似。&lt;/p&gt;&#10;&lt;p&gt;无论何时，目标变量都被视为分类变量或者数值型变量。如果以数值型变量作为分类变量，当该变量取值小于10时，Rattle会自动将其视为分类变量（默认）。结合建模目的，这意味着只能对其构建分类模型。通过选择Data菜单下的Numeric按钮可以对该经验设置进行调整，从而能够对其构建回归类预测模型。&lt;/p&gt;&#10;&lt;h4 id="权重计算和角色"&gt;&lt;a href="#%e6%9d%83%e9%87%8d%e8%ae%a1%e7%ae%97%e5%92%8c%e8%a7%92%e8%89%b2" class="header-anchor"&gt;&lt;/a&gt;权重计算和角色&#10;&lt;/h4&gt;&lt;p&gt;最后一个与Data菜单相关的确认选项是Weight Calculator和与之相关的Weight角色。一个变量可以用来表示与每个观测值相关的权重。Weight Calculator允许我们提供一个科包含多个变量以及标准化的公式来计算每个观测值的权重。以audit数据集为例，我们可使用一个包含调整金额的公式，这一公式将给具有较大调整金额的观测值以较大的权重。&lt;/p&gt;&#10;&lt;h3 id="48-命令汇总"&gt;&lt;a href="#48-%e5%91%bd%e4%bb%a4%e6%b1%87%e6%80%bb" class="header-anchor"&gt;&lt;/a&gt;4.8 命令汇总&#10;&lt;/h3&gt;&lt;p&gt;本章用到的R包，命令，函数和数据集如下：&lt;/p&gt;&#10;&lt;p&gt;&amp;mdash;&amp;mdash;&amp;ndash;|&amp;mdash;&amp;mdash;&amp;mdash;|&amp;mdash;&amp;mdash;&amp;mdash;&#10;对象 | 包 | 对象描述&#10;audit | 数据集 | rattle包示例数据&#10;clients | 数据集 | 伪数据集&#10;data() | 命令 |&#10;R载入数据&#10;dfedit() | 命令 | 在电子表格中编辑数据框&#10;file.show() | 命令 | 显示数据框&#10;foreign | 包 | 多种数据格式的接口&#10;library() | 命令 | 将包载入到R会话中&#10;file.show() | 命令 | 显示文件夹内容&#10;odbcConnect() | 函数| 连接数据库&#10;paste() | 函数 | 合并字符串&#10;rattle | 包 | 提供示例数据&#10;read.arff() | 函数 | 读入ARFF类型的数据文件&#10;read.csv() | 函数 | 读入逗号分隔符类型的数据文件&#10;read.dbf() | 函数 | 从DBF数据库中读入数据&#10;read.delim() | 函数 | 读入制表符分割型的数据文件&#10;read.spss() | 函数| 读入SPSS相关的数据文件&#10;read.table() | 函数 | 读入文本型数据文件&#10;read.xport() | 函数 | 读入SAS导出的数据文件&#10;readHTMLTable() | 函数 | 从万维网读取数据&#10;risk | 数据集 | 伪数据集&#10;RODBC | 包 | 提供数据库接口&#10;sample() | 函数 | 对数据集进行抽样&#10;save() | 命令 | 将R对象保存为二进制文件&#10;set.seed() | 命令 | 重设生成随机数序列的种子&#10;skel | 数据集 | archetypes包中附带的数据集&#10;sqlColumns() | 函数 | 列示数据库表的列字段&#10;sqlTables() | 函数 | 列出数据集中的表&#10;system.file() | 函数 | 返回R安装路径或者包的路径&#10;weather | 数据集 | rattle包中的数据集&#10;XML| 包 | 读取或者生成XML或者HTML文件&lt;/p&gt;&#10;</description></item><item><title>可转债计算细节</title><link>https://gewutang.cn/2014/03/24/notes-on-cb/</link><pubDate>Mon, 24 Mar 2014 00:00:00 +0000</pubDate><guid>https://gewutang.cn/2014/03/24/notes-on-cb/</guid><description>&lt;p&gt;转债的交易记录以及交割过程比股票要稍显复杂，但是，弄清楚这个过程也很有必要。以2014年3月19号的交易为例。&lt;/p&gt;&#10;&lt;h2 id="转债转股是如何完成和计算的"&gt;&lt;a href="#%e8%bd%ac%e5%80%ba%e8%bd%ac%e8%82%a1%e6%98%af%e5%a6%82%e4%bd%95%e5%ae%8c%e6%88%90%e5%92%8c%e8%ae%a1%e7%ae%97%e7%9a%84" class="header-anchor"&gt;&lt;/a&gt;转债转股是如何完成和计算的&#10;&lt;/h2&gt;&lt;p&gt;假设我们的投资组合在3月19号早上以125.5的价格买入100张中鼎转债，手续费12.5元。收盘之前执行转股。结算后，投资组合里拥有的中鼎股票是1440股，价格为当时市场价格；与此同时，保证金账户增加现金6.41元。那么，问题来了，这里的1440股和6.41元是怎么来的？&lt;/p&gt;&#10;&lt;p&gt;如通常所知，可转债的面值一般是100元，中鼎转债也一样。同时，中鼎转债的转股条款中约定的转股价格是6.94元，因此，根据下列公式：&lt;/p&gt;&#10;&lt;p&gt;$$&#10;\text{每张转债转股后可得股数=转债面值（100元）/转股价格}&#10;$$&#10;可知：&lt;/p&gt;&#10;&lt;p&gt;每张中鼎可转债可得到的转股股数是：&lt;/p&gt;&#10;&lt;p&gt;$$&#10;100/6.94&#10;$$&lt;/p&gt;&#10;&lt;p&gt;那么，100张中鼎转债对应的转股股数就是：&lt;/p&gt;&#10;&lt;p&gt;$$&#10;(100/6.94)*100=1440.992&#10;$$&lt;/p&gt;&#10;&lt;p&gt;在结算的时候，计算结果的整数部分即1440会以中鼎股份股票的形式交割给我们，这就是实际得到的股票数目。不足一股的部分，即0.922乘以转股价格之后以现金形式返给我们，我们得到现金是6.41元。&lt;/p&gt;&#10;&lt;h2 id="如何计算转股之后的盈亏平衡价格"&gt;&lt;a href="#%e5%a6%82%e4%bd%95%e8%ae%a1%e7%ae%97%e8%bd%ac%e8%82%a1%e4%b9%8b%e5%90%8e%e7%9a%84%e7%9b%88%e4%ba%8f%e5%b9%b3%e8%a1%a1%e4%bb%b7%e6%a0%bc" class="header-anchor"&gt;&lt;/a&gt;如何计算转股之后的盈亏平衡价格&#10;&lt;/h2&gt;&lt;p&gt;如果已开通融券业务，在买入转债之后，可以以自己中意的价格 &lt;code&gt;\(p*\)&lt;/code&gt; 卖出可转债,此时交易的利润已经锁定。&lt;/p&gt;&#10;&lt;p&gt;如果没有开通融券业务，则买入转债之后，转股收益取决于第二天的正股价格。在给定转股价的情况下，转债价格和正股价格是线性关系，对应到上面的例子就是：&lt;/p&gt;&#10;&lt;p&gt;转债价格=100/6.94*正股价格&lt;/p&gt;&#10;&lt;p&gt;或者：&lt;/p&gt;&#10;&lt;p&gt;转债价格=14.41*正股价格&lt;/p&gt;&#10;&lt;p&gt;于是有，125.5的买入价格对应正股盈亏平衡价格为125.5÷14.41=8.71。也即，如果第二天的股票价格高于8.71，我们以125.5的价格买入的这笔中鼎转债在转股之后就是盈利的。&lt;/p&gt;&#10;</description></item><item><title>孤独的投资者卡洛·坎奈尔</title><link>https://gewutang.cn/2013/08/05/lonely-investor-carlo-cannell/</link><pubDate>Mon, 05 Aug 2013 00:00:00 +0000</pubDate><guid>https://gewutang.cn/2013/08/05/lonely-investor-carlo-cannell/</guid><description>&lt;p&gt;卡洛·坎奈尔(CarloCannell)是一位名副其实的价值投资者，因拥有一套独特的价值选股方法而闻名。1992年，他在旧金山创建专注于股票多空策略的坎奈尔资产管理公司(CannellCapitalLLC)，成立以来旗舰基金汤加基金(TongaFund)的年均收益率维持在20%左右的水平。&lt;/p&gt;&#10;&lt;p&gt;诱人的回报率自然吸引了众多投资者，不过坎奈尔竭力将资产管理规模控制在8亿美元的水平。作为小盘股捡股者的他不可能在运营大量资金的情况下仍然维持着超高回报率。过去几年，他先后退还了投资者2.5亿美元资金。&lt;/p&gt;&#10;&lt;h3 id="分析师比例指标"&gt;&lt;a href="#%e5%88%86%e6%9e%90%e5%b8%88%e6%af%94%e4%be%8b%e6%8c%87%e6%a0%87" class="header-anchor"&gt;&lt;/a&gt;“分析师比例”指标&#10;&lt;/h3&gt;&lt;p&gt;坎奈尔认为孤独者才能成为更好的基金经理，这一点恰好体现在他关注的对象往往是其他投资者从不关注的领域。巴菲特曾说，理性的人总是比较孤独的，但对于投资者来说，却是最重要的素质。&lt;/p&gt;&#10;&lt;p&gt;坎奈尔与其他价值投资者的另一个共同特质，是认为市场并非有效，因此他宁愿在那些“人迹罕至”的市场角落里“深耕”。&lt;/p&gt;&#10;&lt;p&gt;“我认为无效率的市场比有效率的市场能够提供更大的潜在回报。由于有大量的公司信息分布不合理，这导致了市场失效。因此，我们要用大量时间去发掘很大程度上被投资市场忽视的投资价值。”坎奈尔这样说道。&lt;/p&gt;&#10;&lt;p&gt;目前，美国有超过13000家公司必须向美国证监会提交各种形式的报告以及做出信息披露，其中大多数公司都缺乏研究机构的持续跟踪。坎奈尔把“缺乏持续跟踪”定义为只有三个或者更少的卖方分析师定期发布公司的预期收益报告，因此这些公司缺乏常规的信息流动。&lt;/p&gt;&#10;&lt;p&gt;根据坎奈尔的经验，缺乏信息流动会导致市场估值跟公司的实际内在价值间差异更大。基于这样的理念，坎奈尔创造了一个所谓的“分析师比例”指标。这项指标跟踪上市公司的分析师人数。&lt;/p&gt;&#10;&lt;p&gt;“我们认为一个公司的研究者越少越好。在我们投资组合中大约有65%的企业几乎不被任何分析师关注。”坎奈尔解释道。&lt;/p&gt;&#10;&lt;p&gt;坎奈尔并不认为根据这项指标筛选个股是最科学的，但的确是筛选最具价值产品的起点。&lt;/p&gt;&#10;&lt;p&gt;接着，坎奈尔会根据一些传统指标进一步进行筛选。这些指标包括：较低的市净率、较低的账面价值溢价或者折价、市盈率小于股本回报率以及持续产生现金流大于资本支出等。&lt;/p&gt;&#10;&lt;p&gt;位于美国俄亥俄州利普西克的恩尼斯(Ennis)公司是坎奈尔喜欢的典型小盘股。这家公司是一家有着悠久历史的印刷企业。&lt;/p&gt;&#10;&lt;p&gt;坎奈尔称：“我们认为这家企业有着非常好的管理机制。他们的竞争力非常强，非常自律，高管也十分诚实。此外，只有两个非常小的机构研究员在研究这家公司。这个公司从不开季度电话会议，也很少对产品进行宣传，正是我们喜欢的公司。”&lt;/p&gt;&#10;&lt;p&gt;坎奈尔从2001年到2006年，一直持有这家公司。在这期间，公司的股价从每股7.5美元一路上涨至26美元。&lt;/p&gt;&#10;&lt;h3 id="古怪的投资理念和方法"&gt;&lt;a href="#%e5%8f%a4%e6%80%aa%e7%9a%84%e6%8a%95%e8%b5%84%e7%90%86%e5%bf%b5%e5%92%8c%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;“古怪”的投资理念和方法&#10;&lt;/h3&gt;&lt;p&gt;除了传统的价值投资分析外，坎奈尔还拥有一些“古怪”的投资理念和方法。&lt;/p&gt;&#10;&lt;p&gt;“投资者其实和放射科医生、机械工程师或者驾驶员一样，通过某种外在的模式来对事物的本质进行判断。而不同水平的人找出外在形态之间关联性的能力不一样。我认为通过这种能力来甄选股票就是我们的优势所在。”坎奈尔这样说道。&lt;/p&gt;&#10;&lt;p&gt;坎奈尔用一个例子说明这种能力的具体表现：“我们在对潜在的卖空对象进行研究的过程中发现，如果一家公司是由非‘六大’会计师事务所进行财务审计，且这家公司的库存比例正不断下降，这时候公司现金流和净收入之间的差距会否扩大与分析师会否研究这家公司有很大关联性。如果分析师对一家公司的研究力度加大，那么这个公司就可能成为我们潜在的做空对象。”&lt;/p&gt;&#10;&lt;p&gt;2010年初，坎奈尔就指出，他已经开始做空德国的太阳能公司。主要原因是，这个行业得到的政府补贴越来越少，其债务规模也达到了极高水平。&lt;/p&gt;&#10;&lt;p&gt;此外，坎奈尔还有更为“独到”的研究指标。他指出，预付指标是他非常关注的数据之一，而这个指标经常被投资者忽略。&lt;/p&gt;&#10;&lt;p&gt;“公司经常说他们的预付资产一般用于保险、广告或进行商战，但这项资金其实经常用于进行行贿。因此这个数据起伏很大，有时会给公司财务带来很大麻烦。如果这个数据伴随的是毛利率下降，那么投资者就需要提高警惕了。因为在下一季的财报中，会计很有可能会加大销售成本，来掩饰他们在预付资金方面的漏洞。”&lt;/p&gt;&#10;&lt;p&gt;在对公司进行财务分析之后，坎奈尔接下来需要做的，是在“信息分布不合理”的情况下，对买入公司的未来发展进行一个系统评估。&lt;/p&gt;&#10;&lt;p&gt;“对于这一点，我们的做法是聘用一个曾在CNBC(美国全国广播公司财经频道)工作过的记者，他每天的工作就是逛街，包括塔吉特百货(Targets)和百思买(BestBuys)等等，然后发现市场的细微变化。”坎奈尔这样说道，“此外我们也订阅大量的行业杂志，比如石油化工行业、殡葬行业等等。”&lt;/p&gt;&#10;&lt;p&gt;坎奈尔近期向SEC提交的13F档案显示，他在截至2013年3月31日的第一季度中，前三大重仓股分别是价值媒体公司(ValuevisionMediaInc)、信息交换解决方案供应商内部链接控股公司(IntraLinksHoldings)，以及多频道电信公司(MultibandCorp)。&lt;/p&gt;&#10;&lt;p&gt;由于坎奈尔非常看重公司的增长潜能，他也不可避免会通过对管理层施压，来改善股价表现。这个时候的他更像是一名积极的“股东行动主义”投资者。&lt;/p&gt;&#10;&lt;h3 id="投资顺应自然法则"&gt;&lt;a href="#%e6%8a%95%e8%b5%84%e9%a1%ba%e5%ba%94%e8%87%aa%e7%84%b6%e6%b3%95%e5%88%99" class="header-anchor"&gt;&lt;/a&gt;投资顺应自然法则&#10;&lt;/h3&gt;&lt;p&gt;在投资方法之外，坎奈尔的古怪念头也随处可见。他被其他价值投资人熟知是因为在2009年的价值投资大会时，曾经将灭绝的物种与投资相比较。&lt;/p&gt;&#10;&lt;p&gt;他指出，史特拉海牛(Hydrodamalisgigas)是一个已经灭绝了的生物。18世纪中叶之前，人类还未穿过白令海峡，这些海牛生活在北太平洋的海岸线上。自从有1500人徒步来到这里后，史特拉海牛被发现，并被人类猎杀，它们在短短27年之后就灭绝了。&lt;/p&gt;&#10;&lt;p&gt;这个道理可以引申到投资中去。“物种就好比是上市公司。一些公司在大环境变化的过程中，总会经历比别人更长的一段适应期，如果不能适应，那么就会灭绝。比如说，餐饮公司受经济危机的冲击要比一些非周期的行业要大。&lt;/p&gt;&#10;&lt;p&gt;坎奈尔认为，巴菲特在投资过程中总会利用类似大自然的天然法则，从而规避很多不必要的风险。因此，利用自然规律获益远比想尽一切办法找出下一个可口可乐公司要容易得多。&lt;/p&gt;&#10;&lt;h3 id="坎奈尔小档案"&gt;&lt;a href="#%e5%9d%8e%e5%a5%88%e5%b0%94%e5%b0%8f%e6%a1%a3%e6%a1%88" class="header-anchor"&gt;&lt;/a&gt;坎奈尔小档案&#10;&lt;/h3&gt;&lt;p&gt;坎奈尔1963年出生在加利福尼亚州，父亲彼得·坎奈尔(PeterB.Cannell)和祖父都是投资者，并各自成立了自己的资产管理公司。在这样的家庭背景影响下，坎奈尔走上投资之路并不意外，但他并非一开始就热爱投资。&lt;/p&gt;&#10;&lt;p&gt;坎奈尔的大学生涯在普林斯顿大学度过，他一开始选择了古典文学专业，但很快发现自己并不喜欢，于是转向了社会学专业。1986年毕业之后，他只身前往南太平洋的岛国——斐济，成为一名自由职业的记者，此后又先后为两家日本公司服务。&lt;/p&gt;&#10;&lt;p&gt;1988年，他开始自己创业，开了一家开发设计桌面音乐乐谱的公司，缺乏管理经验的他很快意识到自己需要到商学院深造，于是选择了牛津大学的坦普顿学院(TempletonCollege)，这段求学经历真正促使他走向了投资行业。&lt;/p&gt;&#10;&lt;p&gt;“我在牛津那段时间投入到投资中，而且是以一种非常学术和理论化的视角来进行投资。”坎奈尔这样说道，“我做了很多关于市场有效论的研究，非常了解这个假说什么时候会失效。在这些研究下，我的投资哲学得以形成，并沿用至今。”&lt;/p&gt;&#10;&lt;p&gt;1992年，在获得MBA学位后不久，坎奈尔创建了坎奈尔资产管理公司。也正是这一年，他与妻子珍妮弗·布拉德利(JenniferT.Bradley)喜结良缘，婚后他们育有三个子女。&lt;/p&gt;&#10;</description></item><item><title>里昂证券最重要的图表：中国外储增长表</title><link>https://gewutang.cn/2012/12/01/the-most-importtant-plot-about-china/</link><pubDate>Sat, 01 Dec 2012 00:00:00 +0000</pubDate><guid>https://gewutang.cn/2012/12/01/the-most-importtant-plot-about-china/</guid><description>&lt;p&gt;几天前，华尔街日报采访了法国里昂证券的研究员Russel Napier。Russel Napier说，目前全球经济已进入早期复苏阶段的希望可能过于乐观了。他说，中国外汇储备增长将出现令人担忧的停滞，而中国外汇储备增长一直是全球经济增长的动力。&lt;/p&gt;&#10;&lt;p&gt;从下图可以看到，中国外汇储备增长率已经在过去五年里急剧下降，并且现在已经接近零增长。Napier说下面这张图表是“世界上最重要的图表”。他说：“在过去20年中，中国外储增长决定了金融市场所有的关键发展动向。印钱措施将美国国债收益率曲线人为压低。它是全球经济增长的基石，而现在这一切结束了。”&lt;/p&gt;&#10;&lt;p&gt;与之相佐证的是eFinancial News的一则报道：&lt;/p&gt;&#10;&lt;p&gt;上一次中国外储增长低于10%出现在1990年代末，接着就是科技股市场泡沫破裂，经济衰退。自2001年增长恢复后，经济在那十年间也蓬勃发展。但是在2007年金融危机爆发前，中国外储增长再度下降。&lt;/p&gt;&#10;&lt;p&gt;在这里有必要厘清一下Russel Napier和eFinancial News背后的逻辑。&lt;/p&gt;&#10;&lt;p&gt;在长久的一段时间里，世界经济的增长一直靠中美之间的金融配合驱动的。具体的逻辑是这样的：起点是美国开动印钞机，导致美国消费、投资增加；进一步导致以引入外资和出口为导向的国家（以中国为主）的外汇储备的增加（通过出口赢得外汇）；这些国家利用外储购买美国国债，使资金重新回流到美国，美国信贷增加，消费、投资增加。如此循环不已。&lt;/p&gt;&#10;&lt;p&gt;随着中国经济的发展，中国改变现行发展模式的动力越来越大。这意味着中国将不再像过去那样参与上面的信贷循环。这无疑将在短期内给世界经济带来沉重的打击。世界经济要恢复增长的路径无非两条：第一条，让中国重回过去的角色，这似乎不太可行。那么，就只有寻找一个替代中国的国家；第二条，中国开始扮演接近美国的角色，这样一来，中国需要进行大量的改革措施来适应这一角色。任重道远。&lt;/p&gt;&#10;&lt;p&gt;无论如何世界经济将经历一个艰难的再平衡过程，这个过程已经进行了3年，根据历史经验，还需要2-4年的时间才能走完。对投资者而言，这可能是个好机会。每当经济运行到底部，总是有一堆被低估的证券可供选择。&lt;/p&gt;&#10;&lt;p&gt;获取数据和绘制图形的R代码如下：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;library(XML)&#10;getFX=function(pg){&#10;url=paste(&amp;quot;http://data.caixin.com/macro/macro_indicator_more.html?id=F0010&amp;amp;cpage=&amp;quot;,pg,&amp;quot;&amp;amp;pageSize=30&amp;amp;url=macro_indicator_more.html#top&amp;quot;,sep=&amp;quot;&amp;quot;);&#10;url=htmlParse(url,encoding=&amp;quot;utf-8&amp;quot;);&#10;table=readHTMLTable(url)[[2]]&#10;}&#10;&#10;table=getFX(1)&#10;for(i in 2:7){&#10;temp=getFX(i)&#10;table=rbind(table,temp)&#10;}&#10;write.csv(table,&amp;quot;FX.csv&amp;quot;)&#10;FX=read.csv(&amp;quot;FX.csv&amp;quot;)[,4]&#10;growth=diff(rev(FX))/rev(FX)*100&#10;growth.ts=ts(growth,start=c(1995,5),frequency=12)&#10;plot(growth.ts,type=&amp;quot;h&amp;quot;,col=&amp;quot;yellow2&amp;quot;)&#10;abline(h=0.5,col=&amp;quot;red&amp;quot;,lty=2)&#10;text(1998,1,&amp;quot;1998&amp;quot;)&#10;text(2008,1,&amp;quot;2008&amp;quot;)&#10;text(2012,1,&amp;quot;2012&amp;quot;)&#10;&lt;/code&gt;&lt;/pre&gt;&#10;</description></item><item><title>从历史数据看今日股市</title><link>https://gewutang.cn/2012/11/27/historical-data-and-todays-stock-market/</link><pubDate>Tue, 27 Nov 2012 00:00:00 +0000</pubDate><guid>https://gewutang.cn/2012/11/27/historical-data-and-todays-stock-market/</guid><description>&lt;p&gt;在股市发展史上，人性的贪婪和恐惧总是交替出现的。如果我们假设股市存在一个潜在的合理增长线，那么，贪婪和恐惧则周期性地驱动着股市围绕潜在合理增长线上下波动。在这个假设下，找到潜在的合理增长线、最大偏离幅度及偏离持续期对于我们进行投资就显得很有意义。&lt;/p&gt;&#10;&lt;p&gt;观察一下1999年-2012年中国股市数据的直方图和经验累积分布函数图。我将大于&lt;code&gt;quantile(ssec,p=0.9)&lt;/code&gt;的数据定义为异常值（下图中的黑点部分）。剔除异常值数据之后，拟合出股市的潜在合理增长线（蓝色线）&#10;。&#10;图形显示，中国股市已经步入低估时代（恐惧驱动的时代）一段时间了，然而，还没有见底。未来的底部可能偏离潜在合理增长线在1.5倍标准差附近。&lt;/p&gt;&#10;&lt;p&gt;相关R代码为：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;library(quantmod)&#10;getSymbols(&amp;quot;^SSEC&amp;quot;,from=&amp;quot;1991-01-01&amp;quot;)&#10;ssec=coredata(Cl(SSEC))&#10;&#10;layout(m=matrix(c(1,2,&#10; 3,3),nc=2,byrow=T))&#10;&#10;hist(ssec,prob=T)&#10;lines(density(ssec))&#10;&#10;plot(ecdf(ssec))&#10;abline(h=0.9,lty=2)&#10;abline(v=quantile(ssec,0.9),lty=2)&#10;&#10;plot(ssec,pch=20)&#10;points((1:length(ssec))[ssec&amp;lt; =quantile(ssec,0.9)],ssec[ssec&amp;lt;=quantile(ssec,0.9)],col=&amp;quot;red&amp;quot;,pch=20)&#10;l=lm(ssec[ssec&amp;lt;=quantile(ssec,0.9)]~(1:length(ssec))[ssec&amp;lt;=quantile(ssec,0.9)])&#10;abline(l,col=&amp;quot;blue&amp;quot;)&#10;&#10;h=fitted(l)+2*sd(residuals(l))&#10;lines((1:length(ssec))[ssec&amp;lt;=quantile(ssec,0.9)],h,col=&amp;quot;green&amp;quot;)&#10;&#10;h=fitted(l)-2*sd(residuals(l))&#10;lines((1:length(ssec))[ssec&amp;lt;=quantile(ssec,0.9)],h,col=&amp;quot;green&amp;quot;)&#10;dev.off()&#10;&lt;/code&gt;&lt;/pre&gt;&#10;</description></item><item><title>资本市场的先知先觉</title><link>https://gewutang.cn/2012/05/15/capital-market/</link><pubDate>Tue, 15 May 2012 00:00:00 +0000</pubDate><guid>https://gewutang.cn/2012/05/15/capital-market/</guid><description>&lt;p&gt;广州药业(600332)和白云山A(000522)近期的股价走势淋漓尽致地阐释了资本市场的先知先觉。事情肇始于2011年的价值1080亿元的“王老吉”商标合同争议案，回顾一下重要历史有助于理解资本市场的特性。&lt;/p&gt;&#10;&lt;p&gt;2011年4月，广药向贸仲提出仲裁请求，并提供相应资料；5月王老吉商标案立案，确定当年9月底开庭；后因鸿道集团一直未应诉，开庭时间推迟至2011年12月29日，但当日仲裁并未出结果。&lt;/p&gt;&#10;&lt;p&gt;2012年5月10日，广药集团在其官网发布紧急招聘公告，称其全资子公司广州王老吉大健康产业有限公司，紧急招聘3000名“快消人才”。&lt;/p&gt;&#10;&lt;p&gt;2012年5月11日，广药集团收到中国国际经济贸易仲裁委员会日期为2012年5月9日的裁决书，贸仲裁决：广药集团与加多宝母公司鸿道(集团)有限公司签订的《“王老吉”商标许可补充协议》和《关于“王老吉”商标使用许可合同的补充协议》无效；鸿道(集团)有限公司停止使用“王老吉”商标。该裁决为终局裁决，自作出之日起生效。&lt;/p&gt;&#10;&lt;p&gt;2012年5月13日晚，广药集团发布公告告知上述裁决书。然而，广州药业(600332)和白云山A(000522)的股价在5月3日就开始有所企升。&lt;/p&gt;&#10;&lt;p&gt;对大多数资本市场的利好消息而言，当你知道的时候，那个好消息的利好价值已经被先知先觉者压榨殆尽了，再去跟就真成傻瓜。&lt;/p&gt;&#10;</description></item><item><title>R与金融时间序列分析常见问题集</title><link>https://gewutang.cn/2012/02/03/r-and-questions-in-financial-timeseries-analysing/</link><pubDate>Fri, 03 Feb 2012 00:00:00 +0000</pubDate><guid>https://gewutang.cn/2012/02/03/r-and-questions-in-financial-timeseries-analysing/</guid><description>&lt;p&gt;大概四、五个月前，心血来潮打算总结一下COS论坛上关于金融时间序列分析上的常见问题，期许能够形一个集子以方便有需求者查询使用。因先前从未写过书籍，一时难以把握集子的结构便犹豫了很久。后来，无意中发现了《A Discussion of Time Series Objects for R in Finance》这本册子，读罢便决定以该册子的结构为蓝本来总结金融时间序列分析的常见问题集。问题集结构如下:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;基础篇&#10;&lt;ul&gt;&#10;&lt;li&gt;时间序列对象创建&lt;/li&gt;&#10;&lt;li&gt;时间戳操作&lt;/li&gt;&#10;&lt;li&gt;取子集操作&lt;/li&gt;&#10;&lt;li&gt;缺失值处理&lt;/li&gt;&#10;&lt;li&gt;操作效率度量等&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;技术篇&#10;&lt;ul&gt;&#10;&lt;li&gt;R与ARIMA模型&lt;/li&gt;&#10;&lt;li&gt;GARCH族模型&lt;/li&gt;&#10;&lt;li&gt;VaR（Value at Risk）模型&lt;/li&gt;&#10;&lt;li&gt;极值理论模型等&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;目前，基础篇大致完成，技术篇尚未完善，而已完成部分中定有不少错漏之处，希望发现错误的童鞋们能够及时批评指正。此外，本问题集由王晓伟、熊熹、刘剑锋、杨羽提供初稿，由我最终润色完成。感兴趣的人可以在点击&lt;a class="link" href="https://github.com/dengyishuo/dengyishuo.github.com/blob/master/RFinance/FAQ.pdf" target="_blank" rel="noopener"&#10; &gt;FAQ&lt;/a&gt;下载。&lt;/p&gt;&#10;</description></item><item><title>setSymbolLookup</title><link>https://gewutang.cn/2011/06/02/setsymbollookup/</link><pubDate>Thu, 02 Jun 2011 00:00:00 +0000</pubDate><guid>https://gewutang.cn/2011/06/02/setsymbollookup/</guid><description>&lt;p&gt;用quantmod获取OHLC数据时，如果不知道所有获取的股票的简称，在使用数据时可能会遇到一些麻烦，比如：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;library(quantmod)&#10;getSymbols(&amp;quot;000065.SS&amp;quot;)&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;获取数据后，敲入:&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;000065.SS&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;结果是无法返回所获取的数据。不过，不用着急，这个问题可以用setSymbolLookup来解决：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;setSymbolLookup(myname=list(name=&amp;quot;000065.SS&amp;quot;, src=&amp;quot;yahoo&amp;quot;)) &#10;getSymbols(&amp;quot;myname&amp;quot;) &#10;MYNAME #这里是大写字母&#10;&lt;/code&gt;&lt;/pre&gt;&#10;</description></item><item><title>R与量化投资分析入门书单（更新....）</title><link>https://gewutang.cn/2011/05/31/books-on-quantative-investment/</link><pubDate>Tue, 31 May 2011 00:00:00 +0000</pubDate><guid>https://gewutang.cn/2011/05/31/books-on-quantative-investment/</guid><description>&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;David Ruppert：Statistics and Data Analysis for Financial Engineering&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Stefano M. Iacus：Option Pricing and Estimation of Financial Models with R&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Jon Danielsson：Financial Risk Forecasting: The Theory and Practice of Forecasting Market Risk with Implementation in R and Matlab&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Ngai Hang Chan：Time Series: Applications to Finance with R and S-Plus(R)&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>用R计算协偏度和协峰度</title><link>https://gewutang.cn/2011/05/08/use-r-to-caculate-coskewness-and-cokurtosis/</link><pubDate>Sun, 08 May 2011 00:00:00 +0000</pubDate><guid>https://gewutang.cn/2011/05/08/use-r-to-caculate-coskewness-and-cokurtosis/</guid><description>&lt;p&gt;在传统的金融理论中，均值方差分析假设正态分布，但现实中的数据往往偏离这一假设。当资产收益率不服从正态分布时，仅用协方差不足以解释风险，这时候协高阶矩，比如协偏度和协峰度）就变得重要了。协偏度和协峰度是用于衡量资产收益率分布的高阶协动特性。&lt;/p&gt;&#10;&lt;p&gt;协偏度衡量个股收益对市场极端波动的敏感度。低协偏度的股票可能有更高的预期回报，因为投资者偏好正偏而厌恶负偏，导致协偏度溢价效应。这有助于资产定价和组合优化。协峰度反映尾部风险和市场极端波动的协同性。正峰度表示更多极端值，可能意味着更大的市场风险。峰度还可以帮助评估异常值风险和集中度，这对金融风险预警很重要。&lt;/p&gt;&#10;&lt;p&gt;在金融领域，协偏度和协峰度能更全面评估风险，尤其在市场波动剧烈时更是如此。&lt;/p&gt;&#10;&lt;p&gt;PerformanceAnalytics包中提供了CoSkewness()和CoKurtosis()函数来计算两个资产间的协偏和协峰度。&lt;/p&gt;&#10;&lt;p&gt;例如：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;library(PerformanceAnalytics) #载入包&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## 载入需要的程序包：xts&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## 载入需要的程序包：zoo&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## &#10;## 载入程序包：'zoo'&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## The following objects are masked from 'package:base':&#10;## &#10;## as.Date, as.Date.numeric&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## &#10;## 载入程序包：'PerformanceAnalytics'&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## The following object is masked from 'package:graphics':&#10;## &#10;## legend&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;data(managers) #加载managers数据集&#10;CoSkewness(managers[, &amp;quot;HAM2&amp;quot;, drop=FALSE], managers[, &amp;quot;SP500 TR&amp;quot;, drop=FALSE]) #计算协偏度&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## [1] -2.101289e-06&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code class="language-r"&gt;CoKurtosis(managers[, &amp;quot;HAM2&amp;quot;, drop=FALSE], managers[, &amp;quot;SP500 TR&amp;quot;, drop=FALSE]) #计算协峰度&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## [1] 2.579066e-06&#10;&lt;/code&gt;&lt;/pre&gt;&#10;</description></item><item><title>VaR和历史模拟法及R语言</title><link>https://gewutang.cn/2010/12/15/var-calculation-using-historical-simulation/</link><pubDate>Wed, 15 Dec 2010 00:00:00 +0000</pubDate><guid>https://gewutang.cn/2010/12/15/var-calculation-using-historical-simulation/</guid><description>&#10;&#10;&#10;&lt;pre class="r"&gt;&lt;code&gt;library(showtext)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Loading required package: sysfonts&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Loading required package: showtextdb&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;font_add(&amp;quot;SimHei&amp;quot;, &amp;quot;SimHei.ttf&amp;quot;)&#10;showtext_auto()&lt;/code&gt;&lt;/pre&gt;&#10;&lt;div id="引言" class="section level2"&gt;&#10;&lt;h2&gt;引言&lt;/h2&gt;&#10;&lt;p&gt;现代金融领域的计量工作分为两大块，即资产定价和风险度量。而资产定价又是以度量风险并为风险定价为基础，由此可见，风险度量工作实际上是现代金融计量领域的核心。金融领域度量风险的方法有很多，其中应用最多的是方差、最大回撤和 VaR 等。&lt;/p&gt;&#10;&lt;p&gt;在业界，VaR 不仅单纯作为风险管理的工具，在进行投资组合优化时，也会将 VaR 作为重要的过滤指标之一。&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div id="var-的定义" class="section level2"&gt;&#10;&lt;h2&gt;VaR 的定义&lt;/h2&gt;&#10;&lt;p&gt;VaR 是 Value at Risk 的简称，中文译作“在险价值”。它是指在市场正常波动情况下，投资者所持有的投资组合在未来一定时期 &lt;span class="math inline"&gt;\(T\)&lt;/span&gt; 内，在一定置信水平 &lt;span class="math inline"&gt;\(\alpha\)&lt;/span&gt; 下所可能产生的最大可能损失。&lt;/p&gt;&#10;&lt;p&gt;假设投资者持有的投资组合的初始价值为 &lt;span class="math inline"&gt;\(P_{0}\)&lt;/span&gt; ，&lt;span class="math inline"&gt;\(r\)&lt;/span&gt; 为未来一定时期 &lt;span class="math inline"&gt;\(T\)&lt;/span&gt; 对应的收益率。那么，该组合的期末价值为：&lt;/p&gt;&#10;&lt;p&gt;&lt;span class="math display"&gt;\[&#10;P_{T}=P_{0}(1+r_{T})&#10;\]&lt;/span&gt;&#10;&lt;span class="math inline"&gt;\(r\)&lt;/span&gt; 可视作随机变量，若假设在某一置信水平下，该投资组合的最低价值为 &lt;span class="math inline"&gt;\(P^*\)&lt;/span&gt; ，则：&lt;/p&gt;&#10;&lt;p&gt;&lt;span class="math display"&gt;\[&#10;P_{T}^*=P_{0}(1+r_{T}^*)&#10;\]&lt;/span&gt;&#10;显然，根据VaR的定义可知，其等于投资组合的最低价值和初始价值之差：&lt;/p&gt;&#10;&lt;p&gt;&lt;span class="math display"&gt;\[&#10;VaR_{\alpha}=-P_{0}r_{\alpha}^*&#10;\]&lt;/span&gt;&#10;可见，计算 VaR 值等价于计算一定置信水平下的投资组合的最低价值 &lt;span class="math inline"&gt;\(P^*\)&lt;/span&gt; 或最低收益率 &lt;span class="math inline"&gt;\(r^*\)&lt;/span&gt; 。而计算最低价值或最低收益率则需依赖于价格序列或收益率序列的分布或概率密度函数。换句话说，计算金融资产序列的分布函数或概率密度函数正是计算 VaR 值的核心之处。&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div id="var-的算法" class="section level1"&gt;&#10;&lt;h1&gt;VaR 的算法&lt;/h1&gt;&#10;&lt;p&gt;清楚了 VaR 的定义，计算 VaR 的方法也就呼之欲出了。目前，常用的 VaR 算法可以分为参数法即方差-协方差法、蒙特卡洛模拟法以及非参数方法即历史模拟法。在 VaR 的应用过程中，人们也对 VaR 的上述算法进行了扩展。比如，在方差-协方差方法下人们提出了指数级权平均模型计算方差或者结合 Garch 类模型计算方差进而计算 VaR 的方法。&lt;/p&gt;&#10;&lt;div id="历史模拟法" class="section level2"&gt;&#10;&lt;h2&gt;历史模拟法&lt;/h2&gt;&#10;&lt;p&gt;历史模拟法是最简单的计算 VaR 的方法。它假设投资组合未来的波动与投资组合的历史数据完全一致，因此，计算投资组合的未来 VaR 就等同于计算历史数据的既有 VaR 。&lt;/p&gt;&#10;&lt;p&gt;历史模拟法的步骤为：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;搜集历史数据&lt;/li&gt;&#10;&lt;li&gt;计算历史数据的几何收益率&lt;/li&gt;&#10;&lt;li&gt;对收益率进行排序并计算给定置信水平的下分位数&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/div&gt;&#10;&lt;div id="单资产-var-的计算及其r实现" class="section level2"&gt;&#10;&lt;h2&gt;单资产 VaR 的计算及其R实现&lt;/h2&gt;&#10;&lt;p&gt;下面以计算单个资产的VaR为例：&lt;/p&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# 加载必要包&#10;if (!require(&amp;quot;quantmod&amp;quot;)) install.packages(&amp;quot;quantmod&amp;quot;)&#10;library(quantmod)&#10;&#10;# 获取苹果公司股票数据&#10;getSymbols(&amp;quot;AAPL&amp;quot;, src = &amp;quot;yahoo&amp;quot;, from = Sys.Date() - 365, to = Sys.Date())&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;AAPL&amp;quot;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# 计算对数收益率&#10;returns &amp;lt;- na.omit(periodReturn(AAPL, period = &amp;#39;daily&amp;#39;, type = &amp;#39;log&amp;#39;))&#10;&#10;# 设置置信水平 (95%)&#10;confidence_level &amp;lt;- 0.95&#10;&#10;# 历史模拟法计算VaR&#10;historical_var &amp;lt;- -quantile(returns, probs = 1 - confidence_level)&#10;&#10;# 打印结果&#10;cat(&amp;quot;历史模拟法计算的每日VaR（95%置信水平）:&amp;quot;, round(historical_var*100, 2), &amp;quot;%\n&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## 历史模拟法计算的每日VaR（95%置信水平）: 3.22 %&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# 可视化结果&#10;hist(returns, breaks = 50, main = &amp;quot;日收益率分布与VaR（95%）&amp;quot;,&#10; xlab = &amp;quot;日收益率&amp;quot;, col = &amp;quot;lightblue&amp;quot;, border = &amp;quot;white&amp;quot;)&#10;abline(v = -historical_var, col = &amp;quot;red&amp;quot;, lwd = 2)&#10;text(x = -historical_var, y = par(&amp;quot;usr&amp;quot;)[4]*0.9, &#10; labels = paste(&amp;quot;VaR =&amp;quot;, round(historical_var*100, 2), &amp;quot;%&amp;quot;), &#10; pos = 2, col = &amp;quot;red&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;&lt;img src="https://gewutang.cn/2010/12/15/var-calculation-using-historical-simulation/index_files/figure-html/unnamed-chunk-1-1.png" width="672" /&gt;&lt;/p&gt;&#10;&lt;p&gt;也可以直接用PerformanceAnalytics包中的VaR函数计算历史模拟法下的VaR值：&lt;/p&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# 加载必要包&#10;if (!require(&amp;quot;quantmod&amp;quot;)) install.packages(&amp;quot;quantmod&amp;quot;)&#10;if (!require(&amp;quot;PerformanceAnalytics&amp;quot;)) install.packages(&amp;quot;PerformanceAnalytics&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## Loading required package: PerformanceAnalytics&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## &#10;## Attaching package: &amp;#39;PerformanceAnalytics&amp;#39;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## The following object is masked from &amp;#39;package:graphics&amp;#39;:&#10;## &#10;## legend&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;library(quantmod)&#10;library(PerformanceAnalytics)&#10;&#10;# 获取苹果公司股票数据（过去250个交易日）&#10;getSymbols(&amp;quot;AAPL&amp;quot;, src = &amp;quot;yahoo&amp;quot;, from = Sys.Date() - 365, to = Sys.Date())&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;AAPL&amp;quot;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# 计算对数收益率&#10;returns &amp;lt;- na.omit(ROC(Cl(AAPL))) # 等效于 log(Cl(AAPL)/lag(Cl(AAPL)))&#10;&#10;# 使用PerformanceAnalytics包计算历史模拟法VaR（95%置信水平）&#10;var_result &amp;lt;- VaR(&#10; R = returns,&#10; p = 0.95,&#10; method = &amp;quot;historical&amp;quot;,&#10; portfolio_method = &amp;quot;single&amp;quot;&#10;)&#10;&#10;# 提取并格式化结果&#10;historical_var &amp;lt;- abs(var_result[1,]) # VaR值通常取正数表示损失&#10;confidence_level &amp;lt;- attr(var_result, &amp;quot;cl&amp;quot;)&#10;&#10;# 输出结果&#10;cat(&amp;quot;PerformanceAnalytics计算的每日VaR（&amp;quot;, confidence_level*100, &amp;quot;%置信水平）:&amp;quot;,&#10; round(historical_var*100, 2), &amp;quot;%\n&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## PerformanceAnalytics计算的每日VaR（ %置信水平）: 3.22 %&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# 可视化收益率分布及VaR&#10;hist(returns, breaks = 50, main = &amp;quot;日收益率分布与VaR（历史模拟法）&amp;quot;,&#10; xlab = &amp;quot;日收益率&amp;quot;, col = &amp;quot;lightblue&amp;quot;, border = &amp;quot;white&amp;quot;)&#10;abline(v = -historical_var, col = &amp;quot;red&amp;quot;, lwd = 2)&#10;text(x = -historical_var, y = par(&amp;quot;usr&amp;quot;)[4]*0.9,&#10; labels = paste(&amp;quot;VaR =&amp;quot;, round(historical_var*100, 2), &amp;quot;%&amp;quot;),&#10; pos = 2, col = &amp;quot;red&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;&lt;img src="https://gewutang.cn/2010/12/15/var-calculation-using-historical-simulation/index_files/figure-html/unnamed-chunk-2-1.png" width="672" /&gt;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;div id="多资产投资组合的-var-计算及其-r-实现" class="section level2"&gt;&#10;&lt;h2&gt;多资产投资组合的 VaR 计算及其 R 实现&lt;/h2&gt;&#10;&lt;p&gt;用历史模拟法计算多资产投资组合的 VaR 与单资产思路类似，唯一不同的是要按照当前投资组合中各资产的权重计算投资组合的历史收益率。&lt;/p&gt;&#10;&lt;p&gt;具体R代码如下:&lt;/p&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# 加载必要包&#10;library(quantmod) # 金融数据获取&#10;library(dplyr) # 数据处理&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## &#10;## ######################### Warning from &amp;#39;xts&amp;#39; package ##########################&#10;## # #&#10;## # The dplyr lag() function breaks how base R&amp;#39;s lag() function is supposed to #&#10;## # work, which breaks lag(my_xts). Calls to lag(my_xts) that you type or #&#10;## # source() into this session won&amp;#39;t work correctly. #&#10;## # #&#10;## # Use stats::lag() to make sure you&amp;#39;re not using dplyr::lag(), or you can add #&#10;## # conflictRules(&amp;#39;dplyr&amp;#39;, exclude = &amp;#39;lag&amp;#39;) to your .Rprofile to stop #&#10;## # dplyr from breaking base R&amp;#39;s lag() function. #&#10;## # #&#10;## # Code in packages is not affected. It&amp;#39;s protected by R&amp;#39;s namespace mechanism #&#10;## # Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning. #&#10;## # #&#10;## ###############################################################################&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## &#10;## Attaching package: &amp;#39;dplyr&amp;#39;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## The following objects are masked from &amp;#39;package:xts&amp;#39;:&#10;## &#10;## first, last&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## The following objects are masked from &amp;#39;package:stats&amp;#39;:&#10;## &#10;## filter, lag&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## The following objects are masked from &amp;#39;package:base&amp;#39;:&#10;## &#10;## intersect, setdiff, setequal, union&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;library(ggplot2) # 可视化&#10;&#10;# ========== 参数设置 ==========&#10;symbols &amp;lt;- c(&amp;quot;AAPL&amp;quot;, &amp;quot;GOOG&amp;quot;, &amp;quot;MSFT&amp;quot;) # 资产代码（苹果、谷歌、微软）&#10;weights &amp;lt;- c(0.5, 0.3, 0.2) # 资产权重（总和为1）&#10;portfolio_value &amp;lt;- 1e7 # 投资组合当前价值（假设1千万元）&#10;confidence_level &amp;lt;- 0.95 # 置信水平&#10;start_date &amp;lt;- &amp;quot;2020-01-01&amp;quot; # 数据开始日期&#10;end_date &amp;lt;- &amp;quot;2023-12-31&amp;quot; # 数据结束日期&#10;&#10;# ========== 1. 获取历史价格数据 ==========&#10;getSymbols(symbols, src = &amp;quot;yahoo&amp;quot;, from = start_date, to = end_date)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;AAPL&amp;quot; &amp;quot;GOOG&amp;quot; &amp;quot;MSFT&amp;quot;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# 提取收盘价并合并&#10;prices &amp;lt;- merge(Cl(get(symbols[1])), Cl(get(symbols[2])), Cl(get(symbols[3])))&#10;colnames(prices) &amp;lt;- symbols&#10;&#10;# 清理缺失值（确保日期对齐）&#10;prices_clean &amp;lt;- na.omit(prices)&#10;&#10;# ========== 2. 计算各资产对数收益率 ==========&#10;returns &amp;lt;- data.frame(&#10; AAPL = as.numeric(Delt(prices_clean$AAPL)),&#10; GOOG = as.numeric(Delt(prices_clean$GOOG)),&#10; MSFT = as.numeric(Delt(prices_clean$MSFT))&#10;) %&amp;gt;% na.omit() # 去除首行NA&#10;&#10;# ========== 3. 计算投资组合每日收益率 ==========&#10;# 将收益率转换为矩阵进行加权计算&#10;returns_matrix &amp;lt;- as.matrix(returns)&#10;portfolio_returns &amp;lt;- returns_matrix %*% weights&#10;&#10;# ========== 4. 历史模拟法计算VaR ==========&#10;# 按升序排列组合收益率（损失为负值）&#10;sorted_returns &amp;lt;- sort(portfolio_returns)&#10;&#10;# 确定分位数位置&#10;n &amp;lt;- length(sorted_returns)&#10;var_index &amp;lt;- floor((1 - confidence_level) * n)&#10;var_quantile &amp;lt;- sorted_returns[var_index]&#10;&#10;# 计算VaR绝对值&#10;VaR &amp;lt;- abs(var_quantile) * portfolio_value&#10;&#10;# ========== 5. 输出结果 ==========&#10;cat(&amp;quot;========== 计算结果 ==========\n&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## ========== 计算结果 ==========&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;cat(&amp;quot;置信水平:&amp;quot;, confidence_level * 100, &amp;quot;%\n&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## 置信水平: 95 %&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;cat(&amp;quot;历史数据天数:&amp;quot;, n, &amp;quot;\n&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## 历史数据天数: 1005&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;cat(&amp;quot;VaR分位数对应收益率:&amp;quot;, round(var_quantile * 100, 2), &amp;quot;%\n&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## VaR分位数对应收益率: -2.94 %&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;cat(&amp;quot;组合VaR值:&amp;quot;, round(VaR, 2), &amp;quot;元\n&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre&gt;&lt;code&gt;## 组合VaR值: 294069.7 元&lt;/code&gt;&lt;/pre&gt;&#10;&lt;pre class="r"&gt;&lt;code&gt;# ========== 6. 可视化== ==========&#10;# 绘制组合收益率分布直方图&#10;ggplot(data.frame(Return = portfolio_returns), aes(x = Return)) +&#10; geom_histogram(bins = 50, fill = &amp;quot;lightblue&amp;quot;, color = &amp;quot;black&amp;quot;) +&#10; geom_vline(xintercept = var_quantile, color = &amp;quot;red&amp;quot;, linewidth = 1) +&#10; labs(title = &amp;quot;投资组合历史收益率分布与VaR&amp;quot;,&#10; x = &amp;quot;收益率&amp;quot;, y = &amp;quot;频数&amp;quot;) +&#10; annotate(&amp;quot;text&amp;quot;, x = var_quantile, y = Inf, &#10; label = paste0(confidence_level * 100, &amp;quot;% VaR: &amp;quot;, round(VaR, 2), &amp;quot;元&amp;quot;),&#10; color = &amp;quot;red&amp;quot;, vjust = 1.5, hjust = -0.1) +&#10; theme_minimal()&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;&lt;img src="https://gewutang.cn/2010/12/15/var-calculation-using-historical-simulation/index_files/figure-html/unnamed-chunk-3-1.png" width="672" /&gt;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;</description></item></channel></rss>