← All tools · Guides

Local China A-share sync: daily bars for a watchlist, including after a missed boot

Local review series, part 2. The watchlist lands in SQLite after the close. If the computer was off, the task runs when it comes back.

This is part 2 of the Chinese series on a local review stack. The previous part, Python and an empty SQLite file, is the Chinese local Python and SQLite note. That note is not this article. Rate limits, adjustment, and the Chinese column names are covered in more detail in AKShare into SQLite. That walkthrough is not this article either.

Short answer: keep a short watchlist in stocks.txt, append only the missing forward-adjusted daily bars to D:/quant/astock.db, and register a weekday 18:00 task that still runs if the PC was off. Check the log for done before you trust it.

How to choose: Keep the job on the computer you already use for review. The previous note in the Chinese series creates the Python environment, the logs folder, and an empty SQLite file at D:/quant/astock.db. The daily table is code, date, open, high, low, close, volume, with a primary key on code and date. This note fills that table from a short watchlist. Put the codes you hold or watch in D:/quant/scripts/stocks.txt, one per line, and stay under a few dozen names. The script reads MAX(date) for each code, asks AKShare for forward-adjusted daily bars from the next day through 20991231, renames the Chinese columns, and skips a row when the primary key is already there. Register it in Windows Task Scheduler for 18:00 Monday through Friday. Set it to run whether or not you are logged on, and turn on run as soon as possible after a scheduled start is missed, so a shutdown does not leave a gap. That catch-up is what the Chinese title means by starting after boot. It is not a separate At startup trigger. Point the task at a bat file that appends stdout and stderr to a dated log, then use Run once before you trust the schedule. The full-market job, cron at 18:30, and a universe from stock_info_a_code_name are a different article. The review note that reads this database is a different article, and it is still Chinese-only. This page is not the tool-order guide and not the site FAQ.

Who it is for: Someone who already has local Python and the SQLite file from the previous note, watches a short China A-share list, and wants those daily bars written after the close even when the PC was off at 18:00. What you need is the watchlist file, the incremental script, the three Task Scheduler settings, and the log you open when the last result is not 0.

Who it is not for: Someone who wants the whole A-share universe, a server that stays on, or a commercial data contract. The full-market job is the AKShare database walkthrough. A machine that must stay awake starts with the cloud server notes. This page is also not the tool-order guide, not the site FAQ, and not the review-note article that writes the evening summary. Do not run the job during the session. The current day's bar is unfinished. A laptop that sleeps will not wake itself for the task. Disable sleep, or accept the catch-up at the next boot.

The same walkthrough in Chinese is a local watchlist sync that catches up after boot. Storing the whole market, on a schedule aimed at a server, is AKShare into SQLite. The same article in Chinese is the Chinese AKShare database note. That note is not this article. The next part of this series, an evening review written from this database, is the Chinese review-note article. That article is not this one either.

Facts below follow the Chinese walkthrough. The commands were not re-run for this English page. This is not investment advice. Interface behavior follows the current AKShare release.

01 · The script: a watchlist, then only the missing days

Start with D:/quant/scripts/stocks.txt. One code per line. Keep it to the names you hold and the names you actually watch. A few dozen is the comfortable size:

# update_daily.py — run once after the close
import sqlite3, time
from pathlib import Path
import akshare as ak
import pandas as pd

ROOT = Path("D:/quant")
DB = ROOT / "astock.db"
codes = [c.strip() for c in (ROOT / "scripts/stocks.txt").read_text().splitlines() if c.strip()]

conn = sqlite3.connect(DB)
for code in codes:
    # Continue from the day after the latest stored date. That is the incremental step.
    row = conn.execute("SELECT MAX(date) FROM daily WHERE code=?", (code,)).fetchone()
    start = (pd.Timestamp(row[0]) + pd.Timedelta(days=1)).strftime("%Y%m%d") if row[0] else "20240101"
    df = ak.stock_zh_a_hist(symbol=code, period="daily",
                            start_date=start, end_date="20991231", adjust="qfq")
    if df is None or df.empty:
        continue
    df = df.rename(columns={"日期": "date", "开盘": "open", "最高": "high",
                            "最低": "low", "收盘": "close", "成交量": "volume"})
    for _, r in df.iterrows():
        try:
            conn.execute("INSERT INTO daily VALUES(?,?,?,?,?,?,?)",
                         (code, str(r["date"])[:10], r["open"], r["high"],
                          r["low"], r["close"], r["volume"]))
        except sqlite3.IntegrityError:
            pass                     # already stored -> skip (idempotent)
    time.sleep(0.5)                  # polite pause for the rate limit
conn.commit(); conn.close()
print("done", len(codes))

Run it once by hand: python -X utf8 update_daily.py. Open the file in DB Browser for SQLite and confirm the rows are there. The previous note's table uses PRIMARY KEY(code, date), which is why a second run skips rows it already wrote. The strings in rename are the Chinese names AKShare returns for date, open, high, low, close, and volume.

Use this script when the list is short and the database already lives on this PC. When you want every listed name, a snapshot, and an index series, use AKShare into SQLite instead. That page schedules the job at 18:30 and builds the universe in code. This page does not.

02 · Register it in Windows Task Scheduler

One command from an elevated PowerShell creates the task. The graphical scheduler takes the same settings if you would rather click.

schtasks /Create /TN "astock-daily" /SC WEEKLY /D MON,TUE,WED,THU,FRI /ST 18:00 ^
  /TR "D:\quant\.venv\Scripts\python.exe -X utf8 D:\quant\scripts\update_daily.py" ^
  /F

After it exists, open the task properties and change three defaults:

On macOS the equivalent from the Chinese page is crontab -e and one line: 0 18 * * 1-5 /Users/you/quant/.venv/bin/python /Users/you/quant/scripts/update_daily.py.

03 · The log is where a failure shows up

Task Scheduler will not tell you that the script crashed. Redirect stdout and stderr. Change the /TR argument, or point it at a bat file:

@rem run_update.bat
@echo off
cd /d D:\quant
.venv\Scripts\python.exe -X utf8 scripts\update_daily.py >> logs\update_%date:~0,4%%date:~5,2%%date:~8,2%.log 2>&1

Set the task's /TR to that bat. The %date% slice on the Chinese page assumes a year-month-day short date, with separators in the fifth and eighth characters. A month-day-year locale will scramble the filename. The logs folder is created by the previous note's directory layout. The redirect does not create it. After every change, right-click the task and choose Run. Do not discover a dead task at the close.

04 · Check it, then maintain it

05 · Pitfalls

The bars are landing on their own. The next note asks a model to write the evening review:

Next: an AI review note after the close →

This is not investment advice. Interface behavior follows the current AKShare release.

Frequently asked questions

How to choose a local watchlist sync that catches up after a missed close?

Keep the job on the computer you already use for review. The previous note in the Chinese series creates the Python environment, the logs folder, and an empty SQLite file at D:/quant/astock.db. The daily table is code, date, open, high, low, close, volume, with a primary key on code and date. This note fills that table from a short watchlist. Put the codes you hold or watch in D:/quant/scripts/stocks.txt, one per line, and stay under a few dozen names. The script reads MAX(date) for each code, asks AKShare for forward-adjusted daily bars from the next day through 20991231, renames the Chinese columns, and skips a row when the primary key is already there. Register it in Windows Task Scheduler for 18:00 Monday through Friday. Set it to run whether or not you are logged on, and turn on run as soon as possible after a scheduled start is missed, so a shutdown does not leave a gap. That catch-up is what the Chinese title means by starting after boot. It is not a separate At startup trigger. Point the task at a bat file that appends stdout and stderr to a dated log, then use Run once before you trust the schedule. The full-market job, cron at 18:30, and a universe from stock_info_a_code_name are a different article. The review note that reads this database is a different article, and it is still Chinese-only. This page is not the tool-order guide and not the site FAQ.

Who it is for?

Someone who already has local Python and the SQLite file from the previous note, watches a short China A-share list, and wants those daily bars written after the close even when the PC was off at 18:00. What you need is the watchlist file, the incremental script, the three Task Scheduler settings, and the log you open when the last result is not 0.

Who it is not for?

Someone who wants the whole A-share universe, a server that stays on, or a commercial data contract. The full-market job is the AKShare database walkthrough. A machine that must stay awake starts with the cloud server notes. This page is also not the tool-order guide, not the site FAQ, and not the review-note article that writes the evening summary. Do not run the job during the session. The current day's bar is unfinished. A laptop that sleeps will not wake itself for the task. Disable sleep, or accept the catch-up at the next boot.

What does the incremental script actually do?

It reads D:/quant/scripts/stocks.txt, one code per line. For each code it selects MAX(date) from daily in D:/quant/astock.db. If that date exists, the next request starts the following day. If the table has no row yet, it starts at 20240101. The call is ak.stock_zh_a_hist with period daily, end_date 20991231, and adjust qfq. Empty frames are skipped. Chinese columns are renamed to date, open, high, low, close, and volume. Each row is inserted as code, date, open, high, low, close, volume. A duplicate primary key raises IntegrityError and is ignored, so running the script twice does not double a bar. The loop sleeps 0.5 seconds between codes. The Chinese title also names snapshots. The script on that page, and the one here, writes daily bars. A full-market snapshot is stock_zh_a_spot_em, and that call is the other AKShare article.

How do you register the Windows task?

From an elevated PowerShell, schtasks /Create /TN astock-daily /SC WEEKLY /D MON,TUE,WED,THU,FRI /ST 18:00 /TR pointing at D:\quant\.venv\Scripts\python.exe -X utf8 and the script D:\quant\scripts\update_daily.py, with /F to replace an existing task of the same name. On macOS the Chinese page uses crontab: 0 18 * * 1-5, then the venv python and the same script. After you change the task, right-click Run once. Do not wait for the close to find out it never started.

Which three Task Scheduler settings matter?

Open the task properties and change three defaults. Run whether the user is logged on or not. The default, run only when the user is logged on, skips the job when you are signed out. Run the task as soon as possible after a scheduled start is missed. That is the catch-up after a shutdown or a reboot. Stop the task if it runs longer than a limit is fine at the default of several hours. Do not set that limit to one minute. The script finishes in minutes, and a one-minute cap will kill it.

Where do you look when the task fails?

Task Scheduler does not show the Python traceback. Wrap the command in run_update.bat. The bat changes to D:\quant and appends stdout and stderr to logs\update_ plus a date taken from %date%. The slice on the Chinese page assumes a year-month-day short date. Point /TR at that bat. The logs folder is part of the directory layout from the previous note. After the first trading day, the log should contain done and the number of codes. If the last run result is 0x1, or the task did not run, check the logon setting and whether a path with spaces is quoted.

What pitfalls does this walkthrough call out?

Four. A last result of 0x1, or a task that never started, is usually still set to run only when the user is logged on, or a path with spaces was left unquoted. Sleep is not a wake timer. Closing a laptop lid suspends the machine, and the task will not turn it on. Set sleep to never, or accept the catch-up when you next boot. Antivirus products sometimes block python.exe when Task Scheduler launches it and leave no useful error. Whitelist the .venv directory. Do not schedule this during the session. A daily bar pulled before the close is a partial candle. Keep the trigger at 18:00 or later. Forward-adjusted prices drift after dividends, so every few months refresh the whole history instead of trusting the incremental tail forever. This is not investment advice. Interface behavior follows the current AKShare release.