Python教程 第4节:构建简单的单均线交易系统

在上一节中,我们学习了如何获取股票的均线数据。在本节中,我们将尝试搭建一个简单的单均线交易系统。该系统的规则是:当股价突破均线时买入,当股价跌破均线时卖出。我们仍然只使用收盘价,因为盘中价格的噪音太多。

获取股票价格数据

首先,我们需要用到之前讲的,获取股票的价格数据

import yfinance as yf

def get_prices(stock_symbol):
    data = yf.download(stock_symbol)
    return data

确定交易规则

接下来,我们需要确定交易规则:

  1. 如果没有持仓,当股价向上突破均线时满仓买入。
  2. 如果持仓状态下,当股价跌破均线时全部卖出。

这里我们要用到上一节讲的移动平均线的计算方法,以及一个python的内置函数zip用来遍历每个交易日的价格数据。但是要注意sma中最开始的数据是没有的,比如20天均线要到第20天才会有均值数据。这里需要用numpy来确认一下sma是否有数据,代码如下:

import numpy as np

def main():
    prices = get_prices("^NDX")
    sma_20 = prices['Adj Close'].rolling(window=20).mean()  # 20日均线

    # 初始化持仓状态
    in_position = False
    entry_price = 0

    # 遍历每个交易日的价格数据
    for date, price, sma_value in zip(prices.index, prices['Adj Close'], sma_20):
        if not np.isnan(sma_value):  # 忽略均线计算前的NaN值
            if price > sma_value and not in_position:  # 突破均线且当前不在持仓中
                print(f"在 {date} 以价格 {price} 买入")
                in_position = True
                entry_price = price
            elif price < sma_value and in_position:  # 跌破均线且当前持仓中
                print(f"在 {date} 以价格 {price} 卖出")
                in_position = False
                profit = price - entry_price
                print(f"交易盈利: {profit}")

if __name__ == '__main__':
    main()

考虑资本和持仓量

不过这里有个问题,现在的profit是买入和卖出的差价,并不是我们实际的盈利情况。因此,我们引入了初始资本、现金和股票数量等变量,并在交易过程中实时更新这些变量。初始现金等于初始资本,初始股票数量是0。

def main():
    prices = get_prices("^NDX")
    sma_20 = prices['Adj Close'].rolling(window=20).mean()  # 20日均线

    # 初始化持仓状态
    in_position = False
    entry_price = 0
    initial_capital = 1000
    cash = initial_capital
    stock_quantity = 0

    # 遍历每个交易日的价格数据
    for date, price, sma_value in zip(prices.index, prices['Adj Close'], sma_20):
        if not np.isnan(sma_value):  # 忽略均线计算前的NaN值
            if price > sma_value and not in_position:  # 突破均线且当前不在持仓中
                print(f"在 {date} 以价格 {price} 买入")
                in_position = True
                entry_price = price
                stock_quantity = cash / price
                cash = 0
                print(f"买入股票数量{stock_quantity},现金清零")
            elif price < sma_value and in_position:  # 跌破均线且当前持仓中
                print(f"在 {date} 以价格 {price} 卖出")
                in_position = False
                profit = price - entry_price
                print(f"交易盈利: {profit}")
                cash = stock_quantity * price
                print(f"卖出股票数量{stock_quantity},获得现金{cash}")
        print(f"总资产为{cash + stock_quantity * price}")

if __name__ == '__main__':
    main()

将策略整理为函数

最后,我们将单均线交易策略整理为一个函数,以便于后续测试和调用。

import yfinance as yf
import numpy as np


def get_prices(stock_symbol):
    data = yf.download(stock_symbol)
    return data


def get_simple_moving_average(prices,
                              window_size):
    sma_20 = prices['Adj Close'].rolling(window=window_size).mean()  # 20日均线
    return sma_20


def single_moving_average_strategy(initial_capital, prices, sma_window_size):
    in_position = False
    entry_price = 0
    cash = initial_capital
    stock_quantity = 0
    sma = get_simple_moving_average(prices, sma_window_size)
    # 遍历每个交易日的价格数据
    for date, price, sma_value in zip(prices.index, prices['Adj Close'], sma):
        if not np.isnan(sma_value):  # 忽略均线计算前的NaN值
            if price > sma_value and not in_position:  # 突破均线且当前不在持仓中
                print(f"在 {date} 以价格 {price} 买入")
                in_position = True
                entry_price = price
                stock_quantity = cash / price
                cash = 0
                print(f"买入股票数量{stock_quantity},现金清零")
            elif price < sma_value and in_position:  # 跌破均线且当前持仓中
                print(f"在 {date} 以价格 {price} 卖出")
                in_position = False
                profit = price - entry_price
                print(f"交易盈利: {profit}")
                cash = stock_quantity * price
                print(f"卖出股票数量{stock_quantity},获得现金{cash}")
        print(f"总资产为{cash + stock_quantity * price}")

def main():
    prices = get_prices("^NDX")
    single_moving_average_strategy(1000, prices, 50)

if __name__ == '__main__':
    main()

现在,你可以在修改股票代码和均线长度来回测收益啦。

0 0 votes
Article Rating

Leave a Reply

0 Comments
Inline Feedbacks
View all comments
error: Content is protected !!
Scroll to Top
error: Content is protected !!
Scroll to Top