太棒了!恭喜你成功突破了第一个难关,这是最关键的一步。你能主动要求思路而不是直接要代码,这种学习方式非常值得称赞,对你的抽象能力和编程思维锻炼极大。
下一步的核心目标是:利用你手中的数据,模拟一个交易策略的完整生命周期,并评估它的表现。
我们来分解这个目标,我会给你提供思路和必要的金融知识,你来思考如何用代码实现。
你手中的 vector<StockData>
是原始数据,就像生肉,需要加工才能用。
你的任务:计算移动平均线 (Moving Average, MA)
calculateSMA(const std::vector<double>& prices, int period)
。close
) 的向量,以及一个周期 N
(比如5或20)。i
个元素(i >= N-1
),计算从 i - (N-1)
到 i
这 N 个值的平均值。vector<double>
,里面是每个点位对应的 MA 值。前 N-1
个位置可以设为 0
或一个无效值。sma5
和 sma20
。想一想:你的 StockData
结构体是否需要扩展,来存储这些计算出的指标(如 sma5
, sma20
)?或者单独用两个向量存储,但保持和时间索引对齐?
这是策略的大脑,它根据计算出的指标决定要做什么。
你的任务:遍历数据,在每一个时间点,根据金叉和死叉规则,判断是买入、卖出还是持有。
generateSignals(const std::vector<StockData>& data, const std::vector<double>& smaShort, const std::vector<double>& smaLong)
。这个函数的核心是一个循环,遍历每一天(从足够计算长期均线的那一天开始,比如第20天之后)。bool isHolding = false;
) 来记录当前是否持有股票。这是状态机的简单应用,非常重要。i
天):
!isHolding
(未持仓) 并且发生了 金叉(即 smaShort[i] > smaLong[i]
并且 smaShort[i-1] <= smaLong[i-1]
),则生成一个 BUY
信号。isHolding
(持仓) 并且发生了 死叉(即 smaShort[i] < smaLong[i]
并且 smaShort[i-1] >= smaLong[i-1]
),则生成一个 SELL
信号。HOLD
(持有)。struct TradeSignal { int index; std::string date; enum Action { BUY, SELL } action; double price; };
,并把每个信号存入一个 vector<TradeSignal>
。想一想:为什么判断金叉死叉需要同时看第 i
天和第 i-1
天?(提示:要判断“上穿”和“下穿”这个动作,需要一个时间点上的对比)
这是将信号转化为实际账户变动的过程。
你的任务:根据生成的交易信号列表,模拟买卖操作,计算账户资金和股票持仓的变化。