news 2026/10/15 7:30:47

A股AI量化策略从零搭建指南:三层策略骨架设计与代码实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
A股AI量化策略从零搭建指南:三层策略骨架设计与代码实战

前阵子有朋友问我,“想开通一个基于AI的A股量化策略,应该先干什么?”我问他你说的“开通”指什么,是想在某个平台上点个按钮让系统自动跑,还是想自己从零搭一套能用的东西。他想了想说,应该是后者。然后我又问他,那你觉得第一步是找个模型来预测涨跌吗?他愣了一下说,难道不是吗。

这个场景其实很典型。很多人一听到AI量化,第一反应就是“训练一个模型预测明天涨跌”,进一步的反应就是“模型越复杂越厉害”,再进一步就是“直接上DeepLearning”。但真做过的人都知道,预测模型在整个量化系统里只是很小的一块。更大的工作量在数据怎么喂、信号怎么用、仓位怎么算、订单怎么执行。而这些东西,恰好是你可以用一套清晰的三层骨架把它串起来的。

这篇是“开通A股AI量化策略”系列的上篇,重点讲三层策略骨架的设计思路和代码落地,适合已经有Python基础、懂一点pandas和机器学习概念、但还没有完整跑通过一套量化流程的朋友。内容不涉及任何荐股和收益承诺,纯粹是技术骨架分享。

1. 为什么“三层骨架”是起步的正确姿势

1.1 “开通”背后的实际工作量

先说个扎心的现实:你没法像开通某个云服务那样,输入一行命令就得到一个能赚钱的AI量化策略。所谓的“开通”,其实是由下面这串动作组成的连续过程:

  • 准备行情、财务、基本面等数据,并做清洗对齐;
  • 设计交易信号,让AI模型基于特征输出可操作的预测;
  • 把预测结果转成具体持仓,决定买什么、买多少、什么时候买;
  • 把持仓决策转成实际订单,处理滑点、手续费、停牌、涨跌停等现实约束;
  • 最后才是回测验证、模拟盘观察、小资金试跑,逐步迭代。

这一串动作如果混在一起做,你就会发现代码越写越乱:模型代码里混着仓位逻辑,回测里又塞了订单撮合,改一个参数要牵动十来个函数的调用关系。我很早就吃过这个亏,所以后来所有策略我都强制按层拆开。

1.2 三层各自负责什么,边界如何划分

我用的方案是信号层、组合层、执行层,对应关系非常清晰:

  • 信号层:负责“看”。读取数据、构造特征、训练模型、输出对每只股票的预测或者买入概率。这一层不关心你有多少钱、股票池有多大,只回答一个问题——哪只票值得关注。
  • 组合层:负责“分”。根据信号层的输出,结合风险预算、仓位上限、行业集中度等约束条件,决定每只票配多少仓位、总仓位多少、多久调一次仓。这一层不管具体怎么下单,只管资产怎么分配。
  • 执行层:负责“做”。把组合层给出的目标持仓转成可执行的订单,考虑交易成本、滑点、成交量冲击、开盘集合竞价还是盘中等交易时段,最终生成实际委托。

边界划清楚之后有个很实际的好处:你可以单独替换任何一层。模型不好,只改信号层;仓位控制太激进,只调组合层;换了交易通道,只动执行层。其他两层完全不受影响。

1.3 常见误区:一上来就堆模型,不如先定骨架

我见过不少从“预测涨跌”入手的做法,模型跑出来很兴奋,回测也好看,但一上模拟盘就崩。为什么?因为典型的单层模型策略有两个致命伤:

第一,模型输出的是预测值,不是仓位决策。你预测某只票未来5天会涨3%,然后呢?买多少?全仓?半仓?凭什么?模型自己给不出答案,这是组合层的事。

第二,回测里默认“信号出来就能按收盘价成交”,但现实中会出现两种情况:信号一出,股价立刻跳空高开,你按收盘价根本买不到;或者你的订单太大,直接把价格打上去,成交回报缩水。这是执行层的事。

骨架先搭起来,模型能跑、仓位有约束、订单能落地,这个策略才算真正“开通”了。后面所有深度优化,都建立在骨架不乱的前提下。

2. 数据层与信号层:让AI模型先学会“读盘”

2.1 数据取数与清洗细节

信号层的第一步永远不是建模,而是把数据弄干净。这个环节我踩过的坑比建模多得多。

最常见的坑有三个。一是复权问题:股票分红送股之后,历史价格会跳空,如果你直接用原始价格序列训练模型,模型会学到一堆假跳空信号。所以前复权、后复权要统一,训练和预测必须用同一套复权口径。二是停牌问题:停牌期间没有交易数据,但很多数据接口会补一条平盘记录,看起来“没涨没跌”,实际上这天的收益率根本不该参与训练。三是涨跌停问题:涨停时你买不进去,跌停时你卖不出来,如果训练数据里大量出现“涨停后继续大涨”的样本却不做约束,模型学出来的规律根本无法落地。

我习惯的做法是先建一个统一的数据取数层,每天收盘后抓取日线、分钟线、财务指标,统一转成DataFrame结构,并做基础的完整性检查。数据这一层稳定了,后面特征和模型才有意义。

2.2 特征工程与标签设计

信号层的核心提问方式是:给定截止到今天的全部信息,未来一段时间收益如何。

特征方面,常用的有三类。技术面特征如收益率、波动率、均线偏离、RSI、MACD等;资金面特征如成交额变化率、换手率、量比;基本面特征如市盈率分位数、盈利增速预期等。如果刚开始做,建议从技术面加成交额开始,数据易得、逻辑透明,先跑通全流程再加复杂度。

标签设计则是很多新人最迷惑的地方。你要预测的目标不是“明天涨不涨”(随机性太强),更常见的是未来5日或10日的累计收益。这里有个非常关键的细节:计算未来收益时,必须使用“今天收盘价买入、未来第N天收盘价卖出”这样一个不包含当日价格变化的定义。如果你把当天的收益也算进去,就相当于让模型偷看了当天的收盘结果,属于典型的前视偏差。

这个过程建议用pandas的shift函数做偏移,确保标签在时间上是严格“未来”的。每次写完特征和标签,第一件事就是打印出来人工检查一行数据,确认最后几列的取值确实来自更晚的时间点。

2.3 AI模型选型与信号输出

模型选型我的原则是:先用简单模型跑通,再评估要不要换复杂模型。逻辑回归和梯度提升树(比如LightGBM、XGBoost)是很好的起点,训练快、可解释性强、对特征缺省的容忍度高。

这里多说一句:不要一上来就上LSTM或者Transformer。A股日线数据的样本量看起来不少,但实际上真正有效的独立样本远没有想象中那么多。日线数据一天一根K线,十年也就两千多根,时间序列模型吃数据吃得厉害,很容易过拟合。除非你的特征和样本设计已经非常扎实,否则大概率是做一个花架子。

模型训练好之后,输出通常有两种形式:回归模型输出连续预测值,分类模型输出上涨概率。我建议不管哪种形式,最终都统一转成一个0到1之间的分数,作为信号的“强度”。因为后续组合层需要一个统一的排序依据。

信号阈值也要谨慎设置。分数高不代表一定买入,还要看分数在当下市场里的横向水平、股票池大小和目标持仓数量。比如你想持仓10只票,那信号层就输出候选池前10%的股票,至于要不要、配多少,交给组合层。

3. 组合层与执行层:从信号到下单的最后一公里

3.1 风险预算与仓位计算

组合层最核心的概念是风险预算。翻译成人话就是:在你这笔钱里,最多能承受多大的回撤。

没有风险预算的仓位策略就是赌博。我见过有人单吊一只票,信号强就全仓买入,结果一次大阴线直接亏掉十几个点,后面连续几天都靠运气回本。这本质上不是策略问题,是仓位管理缺位。

我这里给一个简单的落地框架:

  • 设定组合总仓位上限,比如最多80%资金入场,留20%现金应对极端情况;
  • 设定单票最大权重,比如不超过组合净值的10%到15%;
  • 设定行业集中度上限,比如单一行业占比不超过30%,防止持仓相关性过高;
  • 根据模型预测分数排序,选出排名靠前的N只股票,再按等权或分数加权分配目标市值。

等权是最容易被低估的方案。它不依赖模型输出的具体数值精度,只需要排序正确,天然控制了单票风险,实现简单、回测稳定。等权做了一段时间之后,想优化再考虑风险平价、均值方差之类的方案也不迟。

3.2 调仓频率与交易成本的关系

很多回测里没有认真对待交易成本,这是回测虚高的最大来源之一。A股交易至少涉及三块成本:佣金、印花税(卖出时缴纳)、滑点。前两者是硬成本,滑点是软成本。

硬成本的算法很直接。佣金按成交金额乘以万几到千几的比例,有最低5元限制;印花税按卖出金额的千分之一左右收取。滑点则取决于你的订单规模与市场流动性的比值。一只日成交额只有几千万的股票,你一次性卖出几十万,吃到的价格大概率比现在看到的价格差不少。

你可以做一个简单测算:如果组合每年换手10倍,双边交易成本按千分之三算,一年光交易摩擦就是3个百分点。也就是说,模型的年化超额收益如果不到三个点,其实策略是在给券商打工。

所以组合层的调仓周期必须和交易成本一起思考。信号每天更新,不代表每天都要调仓。常见做法是设置一个调仓日,比如每周调一次仓,只有持仓偏离目标比例超过某个阈值时,才执行部分调整,避免频繁进出。

3.3 执行层的现实约束:涨跌停、停牌与滑点

执行层是把组合层的“想买”变成“买到了”的地方。这一步的约束条件非常现实。

首先是涨跌停约束。当你信号很强、股票直接涨停时,你挂的买单大概率排在别人后面,很难成交。回测里如果不做处理,系统会认为“涨停价也买入了”,直接多赚一段收益。到执行层这里,必须对涨停股票做“无法成交”的假设。

其次是停牌约束。持仓股票停牌期间无法卖出,组合层需要依据停牌信息剔除这类持仓,否则目标市值和实际市值会偏差过大。

还有一个容易被忽略的问题是拆分大单。如果你的资金体量已经上到一定程度,一次买入几百万的金额,需要把一个大单拆成多个小单,分散在不同时段分批成交,尽量减少对市场价格的冲击。小资金阶段这个问题不明显,但代码结构上建议提前预留拆单接口。

我做执行层的经验是:宁可放弃一部分信号收益,也要保证成交是可信的。因为回测里“没成交”和“按理想价成交”带来的虚高收益,一上实盘立刻就消失,这种落差最容易让人崩溃。

4. 代码落地:一个最小可跑的A股AI策略骨架

4.1 项目目录与依赖

说了这么多概念,终于到了代码环节。先明确一下:为了方便演示,我这里不依赖任何外部真实行情接口,直接用模拟数据构造了一个小股票池。这样做的好处是,你拿过去立刻就能跑,不需要申请任何数据权限。

建议的项目目录结构:

quant_ai_skeleton/ ├── data/ # 缓存行情与特征数据 ├── signal/ # 特征构造与模型训练预测 ├── portfolio/ # 组合构建与仓位计算 ├── execution/ # 订单生成与成本估算 └── backtest/ # 回测引擎与绩效统计

依赖就是最基础的几个库:pandas、numpy、scikit-learn。如果后续想换LightGBM,那是信号层内部的事,不改其他层代码。

4.2 模拟行情数据与特征构造

下面这段代码生成一个虚拟场景:40只股票、连续250个交易日(约一年)的行情,然后构造核心特征和未来收益标签。

import numpy as np import pandas as pd np.random.seed(42) n_stocks = 40 n_days = 250 dates = pd.bdate_range(end=pd.Timestamp.today(), periods=n_days) stock_ids = [f"S{i:02d}" for i in range(n_stocks)] frames = [] for sid in stock_ids: # 模拟股价随机游走 ret = np.random.normal(0.0002, 0.02, n_days) close = 10 * np.exp(np.cumsum(ret)) open_ = close * (1 + np.random.normal(0, 0.005, n_days)) vol = np.random.uniform(5000, 50000, n_days) # 成交额,单位万元 df = pd.DataFrame({ "date": dates, "stock": sid, "open": open_, "close": close, "volume": vol }) frames.append(df) data = pd.concat(frames, ignore_index=True) data["ret"] = data.groupby("stock")["close"].pct_change() # 特征1:过去5日收益率 data["ret_5d"] = data.groupby("stock")["close"].transform(lambda x: x.pct_change(5)) # 特征2:过去5日波动率 data["vol_5d"] = data.groupby("stock")["ret"].transform(lambda x: x.rolling(5).std()) # 特征3:成交量变化率 data["vol_ratio"] = data.groupby("stock")["volume"].transform( lambda x: x / x.rolling(20).mean() ) # 标签:未来5日收益率,注意shift(-5)确保不包含当天 data["label"] = data.groupby("stock")["close"].transform( lambda x: x.shift(-5) / x - 1 ) data = data.dropna(subset=["ret_5d", "vol_5d", "vol_ratio", "label"]).reset_index(drop=True) print(data.head())

这里的标签设计值得再强调一次:shift(-5)把未来第5天的收盘价和今天对比,标签天然不包含今天当天的收益,也不包含明天的收益,从时间线上是严格“未来5日”的收益。

4.3 信号层:训练一个简单的预测模型

下面把数据按时间切分,前80%训练,后20%作为样本外测试。这里我故意没有做复杂的滚动训练,先让整个流程跑通。

from sklearn.ensemble import RandomForestRegressor feature_cols = ["ret_5d", "vol_5d", "vol_ratio"] split_idx = int(len(data) * 0.8) train = data.iloc[:split_idx] test = data.iloc[split_idx:] model = RandomForestRegressor( n_estimators=100, max_depth=4, min_samples_leaf=20, random_state=42 ) model.fit(train[feature_cols], train["label"]) test["pred"] = model.predict(test[feature_cols])

每一只股票每一天都有一个预测值。预测值本身并不直接买入,下一步我需要把这些预测值聚合成“当前时点每只股票的综合信号”。常见做法是聚合到每个调仓日,比如每周五收盘后,取当天所有股票的预测值,按排名输出候选名单。

# 取每周最后一个交易日作为调仓信号日 test["week"] = test["date"].dt.isocalendar().week.astype(int) signal_dates = test.groupby("week")["date"].max().values signal_df = test[test["date"].isin(signal_dates)].copy() # 按每个调仓日对股票预测值排名,输出分数(百分位) signal_df["score"] = signal_df.groupby("date")["pred"].rank(pct=True) print(signal_df[signal_df["date"] == signal_dates[-1]].sort_values("score", ascending=False))

4.4 组合层与回测:把信号变成持仓与净值

组合层要做的事非常简单直白:在每个调仓日,选出分数最高的N只股票,等权分配仓位,持有到下一个调仓日。下面是向量化回测的核心逻辑:

N = 5 # 持仓数量 holding = {} nav = [] position = None cash = 1_000_000 shares = {} last_close = {} for day in data["date"].sort_values().unique(): day_data = data[data["date"] == day].set_index("stock") is_signal_day = day in signal_dates if is_signal_day: day_signal = signal_df[signal_df["date"] == day] top_stocks = day_signal.nlargest(N, "score")["stock"].tolist() # 换仓:卖出不在目标列表的股票,买入新入选的股票 for sid in list(shares.keys()): if sid not in top_stocks: cash += shares[sid] * day_data.loc[sid, "close"] del shares[sid] for sid in top_stocks: if sid not in shares: price = day_data.loc[sid, "close"] target_value = cash / len(top_stocks) shares[sid] = target_value / price cash -= target_value # 每日计算组合市值 total_value = cash for sid, sh in shares.items(): if sid in day_data.index: total_value += sh * day_data.loc[sid, "close"] nav.append(total_value) nav_series = pd.Series(nav, index=data["date"].sort_values().unique()) daily_ret = nav_series.pct_change().dropna() annual_return = nav_series.iloc[-1] / nav_series.iloc[0] - 1 max_drawdown = (nav_series / nav_series.cummax() - 1).min() sharpe = daily_ret.mean() / daily_ret.std() * np.sqrt(252) print(f"累计收益: {annual_return:.2%}") print(f"最大回撤: {max_drawdown:.2%}") print(f"年化夏普: {sharpe:.2f}")

这套代码做了一些简化:没有计算手续费和滑点、没有处理停牌和涨跌停、也没有考虑现金分红。作为骨架演示是够用的,但真的要拿去验证策略,这些坑在下一节会说清楚。

4.5 跑通之后第一件要做的事

跑通这段代码之后,很多人的第一反应是开始调参提升收益率。我的建议是先别急着优化收益,先做一次“成本敏感性测试”:把回测引擎加上千分之二的双边交易成本,再看净值曲线和之前差多少。这一步能让你对“策略真实可落地性”有个直观感受。

如果加上成本后策略直接从盈利变亏损,问题大概率不是出在信号模型,而是出在换手率太高。换手率是策略的隐形杀手,高换手配合高成本,基本就是给券商打工。

5. 回测中那些坑:过拟合、幸存者偏差与未来函数

5.1 未来函数:最容易犯也最致命的错误

未来函数指的是在回测过程中,使用了当时根本拿不到的信息。最典型的一种就是我在特征代码里用到的.transform没有注意shift,导致当天的信息被用于预测当天。

这里举一个常见的写法问题:有人算“最近5日涨幅”时写成close / close.shift(5) - 1,但忘了在groupby之后先排序;还有人用全量数据训练模型,再用同一批数据的未来部分做测试,模型准确率看起来很高,实际上是在开卷考试。

我的建议是:写完任何特征或标签代码后,手动挑一行数据,沿着代码逻辑从头算一遍,确认没有任何一列的数值引用了未来时间点。这个习惯看起来笨,但真的能拦住大量问题。

5.2 幸存者偏差:股票池的动态问题

A股回测里还有一个经典陷阱:用今天的股票列表去回测过去。今天的成分股里已经剔除了很多当年表现很差的股票(退市、ST、长期停牌),用这个池子回测历史,等于天然排除了最差的一批样本,收益虚高。

正确做法是使用历史某个时点真实存在的股票列表。也就是说,每一期调仓日的股票池,应该是那一天实际在交易、没有被停牌和特别处理的股票。代码上要按日期分别加载当时的股票池,而不是用一张静态表跑完全程。新手最容易忽略,却对回测可信度影响极大。

5.3 过拟合的三个信号

判断模型是否过拟合,不需要什么高级工具,盯住三个信号就够了:

第一,训练集表现远好于测试集。如果训练集预测误差极小、样本外误差骤增,说明模型在背训练数据,不具备泛化能力。第二,参数微调导致绩效剧烈波动。某参数从1改成1.1,年化收益从15%变成-8%,这不是高灵敏度策略,这是过拟合。第三,样本外区间收益显著下降。回测好看但如果把最后一段数据留出来,只训练前面的数据,再在最后一段测试,绩效明显变差,基本可以判定策略失效。

对抗过拟合的实用手段包括:限制模型复杂度(比如把决策树深度控制在4到5)、增加min_samples_leaf、少用特征、多依赖排序而非精确预测。简而言之:不要追求“预测最准”,要追求“排序相对可靠”。

5.4 从回测到模拟盘:还要补哪些课

回测跑通、确认没有未来函数和明显过拟合之后,下一步不是直接上真金白银,而是先跑一段时间的模拟盘。模拟盘的核心价值是验证执行层的假设:你的成交假设是否合理、滑点估算是否够用、数据更新的实时性是否达标。

模拟盘阶段我建议同时记录三个东西:信号发出时间与最终成交时间之间的延迟、下单价格与成交价格之间的差值、每笔订单的类型和成交率。这些记录是你后面优化执行层的原始依据,比任何理论推导都管用。

6. 骨架可以往哪些方向扩展

6.1 信号层的扩展:特征库化与多模型融合

骨架稳定之后,第一个值得扩展的地方是信号层。把当前散落在代码里的特征计算整理成一个特征库,按类别分组,比如动量类、反转类、波动类、资金流类,统一接口管理。这样后续加新特征不用改动模型调用逻辑,模型可以自动消费新特征。

多模型融合也是常见升级方向。比如用逻辑回归、随机森林、LightGBM各出一个分数,然后按等权或按历史表现加权合成一个综合分数。融合的核心价值是降低单一模型的过拟合风险,前提是各模型之间的相关性不要太高,如果所有模型都基于同一批特征,融合的意义会大打折扣。

6.2 组合层的扩展:风险模型与动态调仓

组合层下一步可以考虑引入风险模型。最简单的做法是计算持仓组合的历史波动率和最大回撤,如果回撤超过阈值,自动降低总仓位;回撤恢复后再逐步加回。这就是所谓的“波动率目标策略”,在市场剧烈波动时自动减仓,本质上是在做择时。

动态调仓的方向也很好做:不固定每周调一次,而是设置一个“目标持仓偏离度阈值”,比如某只股票从目标权重偏移超过20%才触发调仓。这样可以在交易成本和持仓稳定性之间取得更好的平衡。

6.3 执行层的扩展:拆单与算法交易

如果你的资金体量增长到了一定程度,执行层就需要引入更精细的拆单逻辑。一个简单的做法是VWAP拆单:把一个大单按时间均匀拆成多个小单,让成交均价尽量贴近市场全天平均价。更复杂的还有根据实时盘口流动性的动态拆单,这已经接近机构级算法的范畴了。

对普通个人投资者来说,执行层做到“限价单加合理滑点假设”已经足够。真正把时间花在信号和组合上,性价比更高。

6.4 关于“下篇”的内容预告

这个系列既然叫“上”,自然有对应的中篇和下篇。中篇我打算讲三层骨架的完整工程化改造,包括数据定时更新、模型滚动重训练、策略监控面板和异常告警,让骨架从“能跑”变成“能稳定跑”。下篇则会深入组合层的风险控制细节,比如风险平价、行业中性化和动态止损,以及部分机构常用的组合优化方法。

回到开头那位朋友的经历:他把想“开通AI策略”这件事拆解成三层骨架之后,第一周就搭出了可运行的版本,虽然收益并不亮眼,但他终于知道自己每天在改的是什么、优化的是什么、报告里那些数字是怎么来的。这种“知道自己每一步在做什么”的感觉,比短期收益重要得多。

如果你也正在准备跑自己的第一套AI量化骨架,我的建议很简单:代码可以模仿,骨架必须自己搭一遍。跑通了再谈优化,优化到位了再谈资金,一步都别跳。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 7:30:45

JUnit 5动态测试实战:用@TestFactory批量生成测试用例

做单元测试这么多年,我越来越认同一个观点:测试用例本身,也应该像业务代码一样可以被“编程”。JUnit 5 的 DynamicTests(动态测试)就是专门干这个的——它让你通过TestFactory方法在运行时批量生成测试用例&#xff0…

作者头像 李华
网站建设 2026/10/15 7:30:35

AI提示词优化3D游戏开发:Three.js与Babylon.js实战

1. 项目概述:当3D游戏开发遇上AI提示词去年用Three.js给客户做产品展示页时,我偶然发现用AI生成代码片段能省下30%的重复劳动。这个发现让我开始系统性整理游戏开发领域的Prompt模板,最终沉淀出这套开箱即用的提示词库。不同于网上那些通用模…

作者头像 李华
网站建设 2026/10/15 7:30:07

TensorFlow实战:从计算图到生产部署的深度解析

1. 为什么“tensorflow”这个标题值得单独拎出来聊“tensorflow”这个词,放在今天的技术语境里,已经不只是某个库的名字了。它更像是一个入口——一个把数学表达、计算图、硬件加速、生产部署串起来的入口。很多人第一次接触深度学习,就是从i…

作者头像 李华
网站建设 2026/10/15 7:29:56

OpenClaw接入A股数据:从零搭建AI盯盘监控系统

说实话,在看到“OpenClaw 接入 A 股数据”这个需求时我第一反应是:终于有人把智能体和真实金融数据流串起来了。过去我们聊 AI Agent,总停留在问答、写文案、跑个 demo,但一旦要接真实世界的动态数据,尤其是 A 股这种高…

作者头像 李华
网站建设 2026/10/15 7:29:20

基于Jackson @JsonView实现一个DTO多套输出规则,告别VO类爆炸

搞后端时间一长,你一定会遇到这种场面:接口刚写完,前端说列表页只需要几个字段,详情页要全量字段,管理后台还要额外塞几个内部字段。产品经理再加一句“顺带把第三方对接的字段也裁剪一下”。于是你打开工程&#xff0…

作者头像 李华
网站建设 2026/10/15 7:28:39

Spring Boot+Vue民宿预订网站开发实战:从房态日历到并发控制

1. 民宿房源预订网站的真实复杂度:这活儿远不止"增删改查"先交代一下背景。我做这个 springboot-java 民宿房源预订网站 vue 项目,起因是帮一个做短租运营的朋友做内部管理系统升级。一开始我以为这就是个标准的信息管理系统——几个列表页、一…

作者头像 李华