回乡修仙之我在A股开超市,一年盈利20%

这几天刷某音,看到有位博主天天晒自己在A股"开超市"的盈利视频。比如6月12日盈利4106元,整个6月目前已经盈利6550元,看得花姐心里直痒痒~那问题来了:在A股搞这个"超市模式",真的像他说的那么赚钱吗?我们还是用实打实的数据来说话

我定了一个简单的策略:

1、股票市值要介于50到200亿之间

2、股票出现日线底分型(某相邻的3个K,中间的K最低价和最高价是3个K中最小值,且中间的K收红,这里只做一个简单的判断,不处理K线的包含关系):

3、这个底分型处于近10个K线的最低点,如下图:

4、11号和10号k相比,如果11号K放量(11k成交量/10K成交量>=1.3) 5、开仓K的开盘价涨幅不超过2%

满足上面5个条件我就买100股。如果开仓以后又出现符合上面5个条件的会继续开仓。期间不设置止损,当股票收益达到某个设定值以后就平仓。

策略有了,接下来看看回测结果。

原计划是根据每天市值动态调整股票池,但是这个数据不好找,于是我简化了下:以2024年6月13日的市值作为筛选基础,选出当时市值在50~200亿之间的所有股票作为股票池

第一次回测我初始资金设置了10万,手续费是5元(买卖一次就花费10元),盈利10%就平仓。回测日期是2024年1月1日到2025年6月13日。

开仓321次,不算没平仓的,盈利221次,胜率68.85%,总收益22.96%,这战绩还不错,相信跑赢了大多数人。

第二次回测,盈利设置成了20%其它的不变。 开仓189次,盈利94个,胜率49.74%,总收益20.65%,没有盈利10%的好,不过也差不太多。

接下来是回测代码

首先是行情数据,一开始打算选baostock和掘金量化的API的,但是下载速度太慢,于是改成从通达信软件直接导出txt行情数据。行情文件名如下格式:

读取txt行情文件我单独写了一个方法

python 复制代码
import pandas as pd
from datetime import datetime

def read_tdx_txt(file_path, encoding='gbk'):
    """
    读取通达信导出的txt格式行情数据
    
    参数:
        file_path (str): 文件路径
        encoding (str): 文件编码,默认'gbk'(通达信导出文件常用编码)
    
    返回:
        pandas.DataFrame: 包含日期、开盘价、最高价、最低价、收盘价、成交量的DataFrame
    """
    # 定义通达信导出的txt文件列名
    columns = ['date', 'open', 'high', 'low', 'close', 'volume','amount']
    
    # 读取文件,处理逗号分隔和表头
    df = pd.read_csv(
        file_path,
        sep=',',           # 逗号分隔符
        encoding=encoding,  # 使用指定编码
        header=1,           # 第二行(索引1)作为表头
        skiprows=0,         # 跳过开头的说明行
        skipfooter=1,       # 跳过末尾的"数据来源"行
        engine='python',    # 用于支持skipfooter参数
        names=columns,
        parse_dates=['date'],  # 自动解析日期列
        dtype={
            'open': float,   # 开盘价为浮点型
            'high': float,   # 最高价为浮点型
            'low': float,   # 最低价为浮点型
            'close': float,   # 收盘价为浮点型
            'volume': int,   # 成交量为整数型
            'amount': float  # 成交额为浮点型
        }
    )
    df.sort_values(by='date', inplace=True)  # 按日期排序
    return df

if __name__ == "__main__":
    file_path = r'F:\tdx_hq\BJ#430198.txt'  # 替换为你的文件路径
    df = read_tdx_txt(file_path)
    print(df)  # 打印前几行数据

回测代码,为了让回测速度快一些,我直接把行情都读取到内存中了,速度是比直接读TXT要快很多,感兴趣的可以把代码复制一份自己改改

回测框架逻辑如下:循环所有交易日,检查持仓是否达到止盈条件,满足就平仓,遍历股票池,是否符合"底分型+量价配合"条件,如果符合则开仓,每天记录账户的净值、持仓和现金方便后期统计。

完整代码如下:

python 复制代码
import pandas as pd
import numpy as np
import os
import data_utils

# ===参数===
initial_cash = 100000
buy_fee = sell_fee = 5
position_size = 100  # 每次买100股
data_path = r'F:\tdx_hq'  # 存行情CSV的路径
start_date = pd.to_datetime('2024-01-01')  # 回测起始日期

# ===读取股票池===
stock_pool = pd.read_excel('stock_pool.xlsx')['代码'].astype(str).tolist()

# ===一次性读取所有股票数据===
stock_data = {}
for stock in stock_pool:
    df = data_utils.read_tdx_txt(os.path.join(data_path, f'{stock}.txt'))
    df = df.sort_values('date').reset_index(drop=True)
    stock_data[stock] = df

# ===初始化状态===
portfolio = {}  # 当前持仓:key = stock_日期, value = dict
trade_log = []  # 交易记录
daily_account = []  # 每日账户信息
cash = initial_cash #现金

# ===获取所有交易日(并集)===
all_dates = sorted(
    d for d in set().union(*[df['date'].tolist() for df in stock_data.values()])
    if d >= start_date
)

# ===辅助函数:判断底分型===
def is_bottom_fractal(prices):
    return prices[1] < prices[0] and prices[1] < prices[2]


# ===回测主循环===
for current_date in all_dates:
    print(current_date)
    stock_value = 0 #持有的股票总市值
    # ===先遍历所有持仓,检查是否平仓===
    closed_positions = []
    for key, pos in portfolio.items():
        stock = pos['stock']
        df = stock_data[stock]
        idx_list = df.index[df['date'] == current_date].tolist()
        if not idx_list:
            continue
        idx = idx_list[0]
        close_price = df.loc[idx, 'close']
        ret = (close_price - pos['buy_price']) / pos['buy_price']
        if ret >= 0.2:
            # 满足收益,平仓
            cash += close_price * position_size - sell_fee
            closed_positions.append(key)
            for r in trade_log:
                if r['stock'] == stock and r['buy_date'] == pos['buy_date'] and r['sell_date'] is None:
                    r['sell_date'] = current_date
                    r['sell_price'] = close_price
                    r['return'] = round(ret, 4)
                    break

    for key in closed_positions:
        del portfolio[key]
        
    

    # ===遍历所有股票,判断是否开仓===
    for stock in stock_pool:
        df = stock_data[stock]
        idx_list = df.index[df['date'] == current_date].tolist()
        if not idx_list:
            continue
        idx = idx_list[0]
        if idx < 13:
            continue

        open_n = df.loc[idx, 'open']
        close_n = df.loc[idx, 'close']
        close_n1 = df.loc[idx - 1, 'close']
        volume_n1 = df.loc[idx - 1, 'volume']
        volume_n2 = df.loc[idx - 2, 'volume']
        recent_low = df.loc[idx - 12:idx, 'low'].min()

        # 判断底分型 + n-2 是最低点 + 开盘涨幅 + 成交量放大
        if not is_bottom_fractal(df.loc[idx - 3:idx - 1, 'low'].values):
            continue
        if not is_bottom_fractal(df.loc[idx - 3:idx - 1, 'high'].values):
            continue
        if not df.loc[idx-2,'open']<df.loc[idx-2,'close']:
            continue
        if df.loc[idx - 2, 'low'] != recent_low:
            continue
        if (open_n - close_n1) / close_n1 > 0.02:
            continue
        if volume_n1 < 1.3 * volume_n2:
            continue

        # 满足开仓条件,直接开仓
        if cash >= open_n * position_size + buy_fee:
            cash -= open_n * position_size + buy_fee
            portfolio_key = f"{stock}_{current_date.strftime('%Y%m%d')}"
            portfolio[portfolio_key] = {
                'stock': stock,
                'buy_price': open_n,
                'buy_date': current_date
            }
            trade_log.append({
                'stock': stock,
                'buy_date': current_date,
                'buy_price': open_n,
                'sell_date': None,
                'sell_price': None,
                'return': None
            })
  

    # 计算持仓的市值
    for key, pos in portfolio.items():
        stock = pos['stock']
        df = stock_data[stock]
        idx_list = df.index[df['date'] == current_date].tolist()
        if not idx_list:
            continue
        idx = idx_list[0]
        close_price = df.loc[idx, 'close']
        stock_value += close_price * position_size
        
    # ===记录每日账户信息===
    daily_account.append({
        'date': current_date,
        'cash': round(cash, 2),
        'total_value': round(stock_value+cash, 2),
        'stock_value': round(stock_value, 2)
    })

# ===输出结果===
trade_df = pd.DataFrame(trade_log)
account_df = pd.DataFrame(daily_account)

trade_df.to_csv('交易记录.csv', index=False, encoding='utf-8-sig')
account_df.to_csv('账户净值.csv', index=False, encoding='utf-8-sig')

这个策略虽说比较简单,但胜在清晰易操作,回测效果也挺稳健。特别是第一版策略(10%止盈)胜率高、回撤小,算是一个不错的"短线半自动超市模型"了。

当然,这只是历史回测,未来未必完全复制。但从策略逻辑看,它符合人性的"逢低潜伏、放量买入"的思路,有一定的实操价值。

以前写个策略要花很多时间,现在只要有清晰的想法,扔给AI就能快速产出,剩下只需人工检查逻辑、微调参数,大大提高了效率。

今天的策略分享就到这啦,喜欢的粉丝记得点个赞、转发支持一下!

相关推荐
拓端研究室TRL14 分钟前
Python古代文物成分分析与鉴别研究:灰色关联度、岭回归、K-means聚类、决策树分析
python·决策树·回归·kmeans·聚类
天天摸鱼的java工程师24 分钟前
如何实现一个红包系统,支持并发抢红包?
后端
稳妥API24 分钟前
Gemini 2.5 Pro vs Flash API:正式版对比选择指南,深度解析性能与成本平衡 - API易-帮助中心
后端
深栈解码28 分钟前
OpenIM 源码深度解析系列(十一):群聊系统架构与业务设计
后端
trow33 分钟前
Spring 手写简易IOC容器
后端·spring
山城小辣椒33 分钟前
spring-cloud-gateway使用websocket出现Max frame length of 65536 has been exceeded
后端·websocket·spring cloud
天天摸鱼的java工程师35 分钟前
谈谈你对 AQS(AbstractQueuedSynchronizer)的理解?
后端
鸡窝头on36 分钟前
Spring Boot 多 Profile 配置详解
spring boot·后端
风之旅人37 分钟前
开发必备"节假日接口"
java·后端·开源
鑫有灵溪39 分钟前
Redis 8 架构评估:企业级缓存方案的技术选型与实践指南
后端