---
title: "Daily Holding-Cost Models with asharechips"
author: "Ruihong Zhao"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Daily Holding-Cost Models with asharechips}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>", fig.width = 6, fig.height = 4)
library(asharechips)
```

## What a cost distribution describes

A distribution assigns a share of circulating stock to each modelled holding
cost. Average cost is weighted by shares, rather than by the number of distinct
price levels:

```{r mean}
chip_mean_cost(c(10, 11, 12), c(50, 20, 30))
```

Actual holders' acquisition costs are not available in ordinary daily market
data. This package instead specifies the assumptions used to carry old weights
forward and allocate new weights.

## A small analytical example

The following data are entirely synthetic, not a real stock history. Each day
has a single transaction price. Dates are deliberately out of order.

```{r input}
daily <- data.frame(
  trade_date = c("20260106", "20260102", "20260105"),
  high = c(12, 10, 11), low = c(12, 10, 11), close = c(12, 10, 11),
  vol = c(100, 100, 100), amount = c(120, 100, 110),
  turnover_rate = c(30, 0, 20)
)
chips <- estimate_chip_distribution(daily)
as.data.frame(chips)
summary(chips)
```

Tushare reports volume in lots of 100 shares and amount in thousand CNY, so VWAP
is `amount * 10 / vol`. See the [daily-data documentation](https://tushare.pro/document/2?doc_id=27)
and [turnover definitions](https://tushare.pro/document/2?doc_id=32).

The first row initializes the distribution at 10 CNY. After turnover of 20 and
30 percentage points on the next two days, the analytical weights are:

```{r analytical}
expected <- c(
  "10 CNY" = exp(-0.5),
  "11 CNY" = (1 - exp(-0.2)) * exp(-0.3),
  "12 CNY" = 1 - exp(-0.3)
)
expected
stopifnot(isTRUE(all.equal(unname(expected), chips$distribution$weight)))
```

At a final close of 12, the 12-CNY weight is break-even; it is not counted as
profitable. The three profit/break-even/loss ratios sum to one.

```{r plot}
plot(chips, main = "Synthetic daily cost distribution")
```

## Model choices and initialization sensitivity

The exponential rule retains `exp(-turnover_rate / 100)` of old weight each day.
It represents homogeneous random replacement. Linear replacement uses turnover
directly, is easier to interpret as a single transfer, and requires rates at
most 100 percentage points. They agree approximately for very small turnover.

The linear update builds on the turnover-based cost-distribution recurrence of
[Liu and Wang (2018)](https://doi.org/10.1016/j.physa.2017.11.154). The
exponential retention transform and each daily price-allocation rule are
explicit package-specific modelling choices.

```{r linear}
linear <- estimate_chip_distribution(daily, turnover_transform = "linear")
as.data.frame(linear)
```

The default initialization is a strong assumption. A short interval with little
turnover can retain most of the first day's assigned weight. The diagnostics
distinguish proposed turnover from the replacement actually applied to that
initialized first row:

```{r diagnostics}
chips$diagnostics[c("trade_date", "replacement_fraction",
                    "applied_replacement_fraction", "initialized_here")]
chips$summary[c("initialization_weight", "history_coverage")]
```

If a distribution immediately before the first date is available, supply it in
the final observation's price basis. Every row then applies turnover:

```{r initial}
initial <- data.frame(price = c(8, 12), weight = c(0.5, 0.5))
with_initial <- estimate_chip_distribution(daily, initial_distribution = initial)
summary(with_initial)
```

## Price allocation and resolution

The VWAP method places new weight at a single daily average price. Typical-price
and close methods offer alternatives when volume and amount are unavailable.
The uniform rule allocates weight by overlaps of grid cells with the daily
low-high range. Daily data do not prove that trades were uniformly distributed.

```{r uniform}
range_data <- data.frame(
  trade_date = "20260102", high = 12, low = 10, close = 11, turnover_rate = 0
)
uniform <- estimate_chip_distribution(range_data, price_method = "uniform", price_step = 0.25)
plot(uniform, main = "Uniform allocation is a modelling assumption")
```

Smaller `price_step` reduces rounding error but increases computation. Cost peaks
and threshold-based profit shares can change with resolution. The nominal central
90-percent interval consists of discrete 5th and 95th weighted quantiles; tied
mass at endpoints can make its contained weight exceed 90 percent.

## Joining already downloaded Tushare tables

The package never downloads data or saves credentials. The following joined
tables are also synthetic:

```{r prepare}
raw_daily <- daily[setdiff(names(daily), "turnover_rate")]
raw_daily$ts_code <- "000001.SZ"
basic <- data.frame(ts_code = "000001.SZ", trade_date = daily$trade_date,
                    turnover_rate = daily$turnover_rate)
factors <- data.frame(ts_code = "000001.SZ", trade_date = daily$trade_date,
                      adj_factor = 1)
input <- prepare_tushare_data(raw_daily, basic, factors, ts_code = "000001.SZ")
estimate_chip_distribution(input, adjustment_col = "adj_factor")
```

Duplicate keys or absent matches are errors. A cutoff can be supplied through
`as_of`, including weekends; the last retained daily observation determines the
factor anchor. When factors are supplied, historical prices are multiplied by
`factor_day / factor_last`. Supply unadjusted daily prices to avoid adjusting
twice. Dividend adjustment creates a comparable price basis rather than literal
historical cash acquisition costs.

## Interpreting limitations

The model cannot identify which cost layers were sold, intraday trade-price
patterns, locked holdings, investor identities, or the costs of new shares.
Issuance, unlocks and repurchases are not modelled. If a `float_share` column is
present, consecutive changes are flagged and produce a warning. Fees and taxes
are excluded. Estimates and sensitivity comparisons describe model behaviour;
they do not predict future returns.

For field definitions and validation rules, see `?estimate_chip_distribution`.
Chinese guidance is available at:

```{r chinese-path}
system.file("README.zh-CN.md", package = "asharechips")
```
