After the close: an AI review note for holdings and a watchlist
Local review series, part 3. After the close, your computer reads the database, calls a model, and pushes one note to your phone.
This is part 3 of the Chinese series on a local AI review system. The previous part, writing China A-share daily bars into local SQLite and catching up on boot, is the Chinese local-sync note. The note reads that database. That note is not this article. The Python and SQLite setup before it is the Chinese environment note, also Chinese-only.
Short answer: after the 18:00 ingest, query holdings and the watchlist from local SQLite, send only those rows to an OpenAI-compatible model, write four parts, save briefs/YYYY-MM-DD.md, and schedule the push at 18:30.
How to choose: An after-close review note is a four-part recap you read yourself. It is not a buy or sell signal. Build it only after the local SQLite file from the previous note already holds today's bars. The model interprets rows you queried. It does not fetch prices, news, or filings. The four parts are fixed. Today's market is the index move and the count of advancers and decliners, in a sentence or two. Each holding gets today's move, where it sits over the last five sessions relative to your cost or a recent high, and one status line, in at most two sentences. The watchlist part names only the symbols whose return or volume is clearly out of line. Tomorrow's list is something worth a look, not a recommendation. Call an OpenAI-compatible client. The Chinese page uses DeepSeek at https://api.deepseek.com with model deepseek-chat, and a real project reads the key from the environment. If that database has no index, pull the last few days with ak.stock_zh_index_daily(symbol="sh000001") and append those rows to the same fact text. Save the note under briefs/, for example briefs/2025-09-01.md. Push it to WeChat with ServerChan or pushplus, the same path as the morning-brief note. That note is not this article. On Windows Task Scheduler, run weekdays at 18:30, half an hour after the 18:00 ingest, so the file you read is today's. Feed the last 5 to 10 sessions, not the whole history. If you do not want a vendor to see a cost basis, leave that field on the machine and send codes and returns only. This page is not the tool-order guide, not the site FAQ, not the morning brief, not the intraday alert note, and not the AKShare SQLite walkthrough.
Who it is for: Someone who already stores China A-share daily bars in a local SQLite file and wants a short written review of holdings and a watchlist after the close, then a push to a phone. The numbers come from that database, not from the model's memory.
Who it is not for: Someone who still needs Python, SQLite, or the daily ingest. Those are the first two notes in this Chinese series, and they do not have an English edition. Someone who wants an alert during the session wants the next note, which is also Chinese-only. Someone who wants a pre-market brief wants a different series. This page does not say what to buy or sell. It is not the tool-order guide, and it is not the site FAQ.
The same walkthrough in Chinese is an after-close AI review note. Storing China A-share bars on a schedule, including column names and adjustment, is AKShare into SQLite. That walkthrough is not this article. The push itself, ServerChan, pushplus, mail, or a Telegram bot, is written out in the morning brief. Reuse that function. That note is not this article. The next part of this series, an alert while the market is open, is the Chinese watchlist-alert note. That note is not this article either.
Facts below follow the Chinese walkthrough. The commands were not re-run for this English page. The Chinese page does not publish a model price, and this page does not add one. Usage and prices follow the vendor's own site. This is not investment advice. The model output is a research note, not a reason to trade.
01 · What the note looks like
Four parts, fixed, readable in about five minutes:
- Today's market. Index move plus how many names rose and fell. One or two sentences.
- Holdings. For each name: today's move, where it sits over the last five sessions (how far from your cost, or from a recent high), and one status line.
- Watchlist movers. Symbols whose return or volume is clearly out of line. Leave the quiet names out.
- Tomorrow. Observations drawn from the rows you supplied. "Worth a look" is the ceiling. A buy or a sell is out of scope.
If a section has nothing to say, say that in one line. Padding is how a daily note turns into something you stop opening.
02 · Query the database, then hand the model the facts
The rule: the model interprets. It does not supply the numbers. Read the facts out of the database and put them in the prompt.
import sqlite3, pandas as pd
conn = sqlite3.connect("D:/quant/astock.db")
codes = "('600519','000858','300750')" # holdings and the watchlist
df = pd.read_sql_query(f"""
SELECT code, date, close, volume FROM daily
WHERE code IN {codes} ORDER BY date""", conn)
conn.close()
# Today's change, the change across the last six bars, and a volume ratio, one line per code.
facts = []
for code, g in df.groupby("code"):
g = g.tail(6).reset_index(drop=True)
if len(g) < 6: continue
chg1 = (g.close.iloc[-1]/g.close.iloc[-2]-1)*100
chg5 = (g.close.iloc[-1]/g.close.iloc[0]-1)*100
vol_ratio = g.volume.iloc[-1] / g.volume.iloc[:-1].mean()
facts.append(f"{code} today {chg1:+.1f}% 5d {chg5:+.1f}% vol_ratio {vol_ratio:.1f}")
data_text = "\n".join(facts)Six bars is the minimum. The one-day change uses the last two closes. The five-session change uses the first and the last of those six rows, which is five steps. The volume ratio is today's volume divided by the mean of the earlier bars in that window. A code with fewer than six rows is skipped. Do not ask the model to fill the gap.
What to include, and what to leave on disk:
- Send the code, today's percent change, the five-session change, and the volume ratio. That is enough for the four parts.
- Keep local a cost basis if you do not want the vendor to store it. You can still mention "near cost" or "far from cost" in your own words after you read the note, or you can add a rounded distance you computed yourself. Do not let the model invent the cost.
- Window the last 5 to 10 sessions. A full history does not make the note wiser. It makes the bill larger and the prompt easier to ignore.
03 · Call the model through an OpenAI-compatible API
# pip install openai (major China model APIs accept this client)
from openai import OpenAI
client = OpenAI(
base_url="https://api.deepseek.com", # swap in your provider
api_key="sk-xxxx", # a real project reads this from the environment
)
resp = client.chat.completions.create(
model="deepseek-chat",
messages=[{"role": "user", "content": PROMPT + data_text}],
)
note = resp.choices[0].message.contentPut the rules in the prompt before the data:
PROMPT = """You are a careful review assistant. Rules:
1) Use only the data I provide. Do not invent any number, news item, or filing.
2) Do not give buy or sell advice. Describe what happened and name the risk.
3) Write four parts: today's market (I will also give you index rows) / holdings / watchlist movers / what to look at tomorrow.
4) At most two sentences per name.
Today's data:
"""The index is the same idea. If the database from the first note has no index series, pull the last few days with ak.stock_zh_index_daily(symbol="sh000001") and append those rows to data_text. That symbol is the Shanghai Composite in AKShare's index helper. Do not type the index move from memory. Column names, rate limits, and adjustment are covered in AKShare into SQLite, which is a different article.
Swap the base_url and the model name for another OpenAI-compatible provider if you already have an account. Do not add a second client "for a better opinion." One model, one prompt, one file per day is the version you can compare with last month.
04 · Archive, then push
Write the note to a dated file such as briefs/2025-09-01.md. A few months later, the useful question is what the model said on that day, next to what the prices actually did. A chat window does not keep that.
Then push it to WeChat with ServerChan or pushplus. The request and the failure log are the same as in the morning brief. Copy that function. Do not invent a second push stack for this one job. That note also lists mail and a Telegram bot if WeChat is the wrong channel. Whichever you pick, a failed send has to land in a log. A silent failure looks like a quiet market.
05 · Schedule it after the ingest
schtasks /Create /TN "ai-review" /SC WEEKLY /D MON,TUE,WED,THU,FRI /ST 18:30 ^
/TR "D:\quant\run_review.bat" /F
# 18:30 is half an hour after the 18:00 ingest, so the database already has todayThree checks before you trust the clock:
- Order. The ingest task from the previous note is 18:00. This task is 18:30. If you flip them, the note describes yesterday and the heading still says today.
- Weekdays. Monday to Friday matches the ingest task. A holiday will still fire. The script can exit when the latest bar is not today. That is cheaper than a paragraph about a market that did not open.
- Path.
run_review.batshould call Python with an absolute path and write stdout to a log. Task Scheduler does not inherit the PATH you use in a terminal.
06 · Pitfalls
- Invented numbers. The only fix is the rule. You provide every figure. The prompt forbids invention. A spot-check compares the note with the database. One invented figure and you tighten the prompt before the next run.
- Privacy. Codes and a cost basis are sent to the model vendor. If that is too much, leave the cost column on disk and send the code and the return.
- Token cost. A few hundred words a day is a small bill. The bill that runs away is the one where you paste the entire history. Send the last 5 to 10 sessions.
- A fluent note that does not help. The value is continuity, and that it forces you to look once a day. It is not a single-day insight. Read it for 30 days before you decide it is useless.
The note waits for the close. The last part of the series pushes while the market is open:
This is not investment advice. The model output is a research note, not a reason to trade.
Frequently asked questions
How to choose an after-close AI review note?
An after-close review note is a four-part recap you read yourself. It is not a buy or sell signal. Build it only after the local SQLite file from the previous note already holds today's bars. The model interprets rows you queried. It does not fetch prices, news, or filings. The four parts are fixed. Today's market is the index move and the count of advancers and decliners, in a sentence or two. Each holding gets today's move, where it sits over the last five sessions relative to your cost or a recent high, and one status line, in at most two sentences. The watchlist part names only the symbols whose return or volume is clearly out of line. Tomorrow's list is something worth a look, not a recommendation. Call an OpenAI-compatible client. The Chinese page uses DeepSeek at https://api.deepseek.com with model deepseek-chat, and a real project reads the key from the environment. If that database has no index, pull the last few days with ak.stock_zh_index_daily(symbol="sh000001") and append those rows to the same fact text. Save the note under briefs/, for example briefs/2025-09-01.md. Push it to WeChat with ServerChan or pushplus, the same path as the morning-brief note. That note is not this article. On Windows Task Scheduler, run weekdays at 18:30, half an hour after the 18:00 ingest, so the file you read is today's. Feed the last 5 to 10 sessions, not the whole history. If you do not want a vendor to see a cost basis, leave that field on the machine and send codes and returns only. This page is not the tool-order guide, not the site FAQ, not the morning brief, not the intraday alert note, and not the AKShare SQLite walkthrough.
Who it is for?
Someone who already stores China A-share daily bars in a local SQLite file and wants a short written review of holdings and a watchlist after the close, then a push to a phone. The numbers come from that database, not from the model's memory.
Who it is not for?
Someone who still needs Python, SQLite, or the daily ingest. Those are the first two notes in this Chinese series, and they do not have an English edition. Someone who wants an alert during the session wants the next note, which is also Chinese-only. Someone who wants a pre-market brief wants a different series. This page does not say what to buy or sell. It is not the tool-order guide, and it is not the site FAQ.
What are the four parts of the note?
Keep the note to four parts you can read in about five minutes. Today's market is the index move plus how many names rose and fell, in one or two sentences. Holdings: for each name, today's move, where it sits over the last five sessions relative to your cost or a recent high, and one status line. Watchlist movers: only the symbols whose return or volume is clearly unusual. Tomorrow: observations the model pulled from the rows you supplied, phrased as something worth a look. That last part is not a recommendation. The prompt caps each name at two sentences.
Why must the numbers come from your database?
The model writes the reading. You supply the facts. Query SQLite, compute today's percent change, the change across the last six bars, and a volume ratio, and paste those lines into the prompt. A figure the model did not receive is a figure you cannot check. The rule in the prompt is explicit: use only the data provided, and do not invent a number, a news item, or a filing. When you spot-check, compare the note with the database. One invented figure is a reason to tighten the prompt.
Which model API do you call?
Any provider that speaks the OpenAI API. The Chinese page installs the openai package and points base_url at https://api.deepseek.com, model deepseek-chat. The snippet shows sk-xxxx and says a real project reads the key from the environment. The prompt states the four rules before the data: no invented figures, no buy or sell advice, four sections, at most two sentences per name. This page does not publish a dollar price. Usage and prices follow the vendor's own site.
Why is the scheduled task at 18:30?
The previous note in the series writes the daily bars with Windows Task Scheduler at 18:00 on weekdays. The review job is a second task, ai-review, Monday to Friday at 18:30, running D:\quant\run_review.bat. The half hour is there so the database you read already contains today. An earlier clock reads yesterday's file and the note looks finished while it is stale. This is the local Windows job. It is not the cloud cron in the morning-brief note, and it is not the AKShare walkthrough.
What pitfalls does this walkthrough call out?
Four. Invented numbers: you provide every figure, the prompt forbids invention, and a spot-check goes back to the database. Privacy: codes and a cost basis leave your machine for the model vendor. If that bothers you, keep cost local and send only the code and the return. Token cost stays small for a few hundred words a day and blows up when you paste the whole history, so send the last 5 to 10 sessions. A fluent note can still be useless. The value is that it shows up every day and that you can read last month's file. Judge it after 30 days, not after one clever paragraph. This is not investment advice. The model output is a research note, not a reason to trade.