老虎证券美股策略——将动量策略日频调仓改成月频

2023-11-16

最近策略频繁回撤,跑不赢标普500指数,所以对策略简单修改,以待后效。
新加入的代码

def get_if_trade_day():
    infile = open('countday.dat','r')
    incontent = infile.read()
    infile.close()
    num=int(incontent)
    if num !=0 :
        num = (num+1)%4
        outfile = open('countday.dat','w')
        outfile.write(str(num))
        outfile.close()
        return False
    else :
        num = (num+1)%4
        outfile = open('countday.dat','w')
        outfile.write(str(num))
        outfile.close()
        return True

在策略文件目录下建立countday.dat文件写入0,在crontab配置里改成每周一晚上9点定时运行,get_if_trade_day()函数会每四次返回一次True,大概四周调仓一次

import os
import logging
import traceback
import pandas as pd
import numpy as np
import talib as ta
import re
import math
import threading
import time
import sys
import signal
import copy
from scipy import stats  # using this for the reg slope
from datetime import datetime
#账户设置包导入
from tigeropen.examples.client_config import get_client_config
#交易包导入
from tigeropen.trade.domain.order import ORDER_STATUS
from tigeropen.trade.request.model import AccountsParams
from tigeropen.common.response import TigerResponse
from tigeropen.tiger_open_client import TigerOpenClient
from tigeropen.trade.trade_client import TradeClient
from tigeropen.quote.request import OpenApiRequest
from tigeropen.common.util.contract_utils import option_contract, future_contract
#行情包导入
from tigeropen.examples.sp500 import save_sp500_tickers as getsp500code
from tigeropen.common.consts import Market, QuoteRight, BarPeriod,Language
from tigeropen.quote.quote_client import QuoteClient

momentum_window = 60  # first momentum window.
momentum_window2 = 90  # second momentum window
minimum_momentum = 60
exclude_days = 5  # excludes most recent days from momentum calculation
#判断可以买入的股票代码
buy_set=set()
final_buy_list=[]
#当前持仓股票代码和数量的字典
cur_quant={}
goal=3
num_of_stocks=3
inv_vola_table=[]
#日志设置
logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s %(levelname)s %(message)s',
                    filemode='a', )
logger = logging.getLogger('TigerOpenApi')
#客户端设置
client_config = get_client_config()
#定义交易客户端
openapi_client = TradeClient(client_config, logger=logger)
#定义行情客户端
quote_client = QuoteClient(client_config, logger=logger)
#获取标普500的20日bars
def get_price(bars_num):
    stocks = read_sp_500code()
    df=pd.DataFrame(columns=['symbol','time','open','high','low','close','volume'])
    #每次取数据要取的条目数量
    items=math.floor(1000/bars_num)
    stock_num=len(stocks)
    print(stock_num)
    roundtrip=math.floor(stock_num/items)
    print(roundtrip)

    for i in range(roundtrip):
        bars = quote_client.get_bars(stocks[i*items:i*items+items],period=BarPeriod.DAY,begin_time=-1, end_time=-1,right=QuoteRight.BR,limit=bars_num)
        df=df.append(bars,ignore_index=True)
        print(bars)
    bars = quote_client.get_bars(stocks[roundtrip*items:stock_num],\
                     period=BarPeriod.DAY,begin_time=-1,end_time=-1,right=QuoteRight.BR,limit=bars_num)
    df=df.append(bars,ignore_index=True)
    df.drop(['time','open','high','low','volume'],axis=1,inplace=True)
    print(df)
  
    return_df=pd.DataFrame(columns=stocks)
    for i in range(len(stocks)):
        close = df[i*bars_num:i*bars_num+bars_num]['close'].values
        print(close)
        print(type(close))
        return_df[stocks[i]]=close
    print(return_df)
    return return_df

def inv_vola_calc(ts):
    """
    Input: Price time series.
    Output: Inverse exponential moving average standard deviation. 
    Purpose: Provides inverse vola for use in vola parity position sizing.
    """
    returns = np.log(ts).diff()
    stddev = returns.ewm(halflife=20, ignore_na=True, min_periods=0,
                         adjust=True).std(bias=False).dropna()
    return 1 / stddev.iloc[-1]

def slope(ts):
    """
    Input: Price time series.
    Output: Annualized exponential regression slope, multipl
    """
    x = np.arange(len(ts))
    log_ts = np.log(ts)
    #print('This is ts',ts)
    #print('This is log_ts:\n',log_ts)
    #print(' ')
    slope, intercept, r_value, p_value, std_err = stats.linregress(x, log_ts)
    #print(slope)
    annualized_slope = (np.power(np.exp(slope), 250) - 1) * 100
    #print('This is annualized_slope',annualized_slope)
    return annualized_slope * (r_value ** 2)  

def generate_trade_info():
    stocks = read_sp_500code()
    hist_window = max(momentum_window,
                      momentum_window2) + exclude_days
    hist=get_price(hist_window)
    print(hist)

    data_end = -1 * exclude_days # exclude most recent data
    momentum1_start = -1 * (momentum_window + exclude_days)
    momentum_hist1 = hist[momentum1_start:data_end]

    momentum2_start = -1 * (momentum_window2 + exclude_days)
    momentum_hist2 = hist[momentum2_start:data_end]

    momentum_list = momentum_hist1.apply(slope)  # Mom Window 1
    momentum_list2 = momentum_hist2.apply(slope)  # Mom Window 2

    # Combine the lists and make average
    momentum_concat = pd.concat((momentum_list, momentum_list2))
    mom_by_row = momentum_concat.groupby(momentum_concat.index)
    mom_means = mom_by_row.mean()

    # Sort the momentum list, and we've got ourselves a ranking table.
    ranking_table = mom_means.sort_values(ascending=False)

    buy_list = ranking_table[:num_of_stocks]
    global final_buy_list
    final_buy_list = buy_list[buy_list > minimum_momentum] # those who passed minimum slope requirement

    # Calculate inverse volatility, for position size.
    global inv_vola_table
    inv_vola_table = hist[buy_list.index].apply(inv_vola_calc)
    
    global buy_set
    buy_set = set(final_buy_list)
    
def trade(account):
    
    #generate_trade_info()
    #account = client_config.paper_account
    curset=get_curset(account)
    #设计pos_local_curset来应对主观交易的问题
    pos_local_curset=get_local_curset(account)
    temp_pos_local_curset = copy.deepcopy(pos_local_curset)

    # Sell positions no longer wanted.
    for security in temp_pos_local_curset:
        if (security not in set(final_buy_list.index)):
            print('preparing substitution')
            print(security)
            contract = openapi_client.get_contracts(security)[0]
            print(cur_quant)
            quant=cur_quant[security]
            print(quant)
            pos_local_curset.remove(security)
            order = openapi_client.create_order(account, contract, 'SELL', 'MKT' , cur_quant[security])
            openapi_client.place_order(order)
    # sum inv.vola for all selected stocks.  

    sum_inv_vola = np.sum(inv_vola_table)            
    vola_target_weights = inv_vola_table / sum_inv_vola
    cur_asset=openapi_client.get_assets(account=account)
    potfolio=cur_asset[0]
    print(potfolio)
    print(potfolio.summary)
    #cash=potfolio.summary.available_funds
    cash=potfolio.summary.net_liquidation*0.5

    print(final_buy_list)
    print(type(final_buy_list))
    for security in set(final_buy_list.index):
        # allow rebalancing of existing, and new buys if can_buy, i.e. passed trend filter.
        weight = vola_target_weights[security]
        contract = openapi_client.get_contracts(security)[0]
            #print(contract)
            #print(type(tobuy_list[i]))
            #print(tobuy_list[i])
        brief=quote_client.get_briefs(symbols=[security],right=QuoteRight.BR)
        latest_price=brief[0].latest_price
        quant=math.floor(cash*weight/latest_price)
        opt='BUY'
        if (security in curset): 
            net=math.floor(cash*weight/latest_price)-cur_quant[security]
            if net > 0:
                quant=net
                if abs(net)/cur_quant[security] < 0.1 :
                    continue
            elif net < 0:
                opt='SELL'
                quant=-net
                if abs(net)/cur_quant[security] < 0.1 :
                    continue
            else: 
                continue
        else:
            pos_local_curset.add(security)
        
        if math.floor(cash*weight/latest_price) == 0 :
            pos_local_curset.remove(security)
        if quant == 0:
            continue

        order = openapi_client.create_order(account, contract, opt, 'MKT' , quant)
        print('buy order sent')
        openapi_client.place_order(order)

    write_pos_local_curset(list(pos_local_curset),account)

       
#position对象:[contract: TVIX/STK/USD, quantity: 5, average_cost: 36.0764, market_price: 0.0]
def get_curset(account):
    pos=openapi_client.get_positions(account=account)
    print(len(pos))
    curset=set()
    global cur_quant
    cur_quant={}
    for i in range(len(pos)):
        print('当前持仓\n',pos[i])
        cont=pos[i].contract
        code = re.search(r'[A-Z]*(?=/STK)',str(cont)).group(0)
        curset.add(code)
        cur_quant[code]=pos[i].quantity
    return curset

def get_local_curset(account):
    if client_config.account == account :
        infile = open('account_local_curset.dat','r')
    elif client_config.paper_account == account :
        infile = open('paper_local_curset.dat','r')
    incontent = infile.read()
    infile.close()
    if incontent.strip() == str(''):
        return set()
    print(incontent)
    incontent=incontent.lstrip('[')
    print(incontent)
    incontent=incontent.rstrip(']\n')
    print(incontent)
    stocks = incontent.split(', ')
    print(stocks)
    print(len(stocks))
    print(eval(stocks[0]))
    new= []
    for i in range(len(stocks)):
        new.append(eval(stocks[i]))
    return set(new)

def write_pos_local_curset(pos_local_curset,account):
    if client_config.account == account :
        outfile = open('account_local_curset.dat','w')
    elif client_config.paper_account == account :
        outfile = open('paper_local_curset.dat','w')
    outfile.write(str(pos_local_curset))
    outfile.close()
#卖出当前所有持仓
def all_off(account):
    pos=openapi_client.get_positions(account=account)
    for i in range(len(pos)):
        contract=pos[i].contract
        quantity=pos[i].quantity
        if quantity>0:
            order = openapi_client.create_order(account, contract, 'SELL', 'MKT' , quantity)
            openapi_client.place_order(order)
        elif quantity<0:
            order = openapi_client.create_order(account, contract, 'BUY', 'MKT' , -quantity)
            openapi_client.place_order(order)
    if client_config.account == account :
        outfile = open('account_local_curset.dat','w')
    elif client_config.paper_account == account :
        outfile = open('paper_local_curset.dat','w')
    outfile.write('')
    outfile.close()

def read_sp_500code():
    infile = open('sp500code.dat','r')
    incontent = infile.read()
    incontent=incontent.lstrip('[')
    incontent=incontent.rstrip(']')
    stocks = incontent.split(', ')
    new= []
    for i in range(len(stocks)):
        new.append(eval(stocks[i]))
    return new

def before_market_open():
    generate_trade_info()
def get_if_trade_day():
    infile = open('countday.dat','r')
    incontent = infile.read()
    infile.close()
    num=int(incontent)
    if num !=0 :
        num = (num+1)%4
        outfile = open('countday.dat','w')
        outfile.write(str(num))
        outfile.close()
        return False
    else :
        num = (num+1)%4
        outfile = open('countday.dat','w')
        outfile.write(str(num))
        outfile.close()
        return True

#Not Yet Open, Pre Market Trading, Market Trading
if __name__ == '__main__':
    if get_if_trade_day() == False:
        print('Dont trade')
        sys.exit(0)
    print('trade')
    if 'account' == sys.argv[2] :
        account = client_config.account
    elif 'paper_account' == sys.argv[2] :
        account = client_config.paper_account
    if sys.argv[1] == 'trade':    
        p = threading.Thread(target=before_market_open)
        p.setDaemon(True)
        p.start()
        time.sleep(10)
        p.join()
        while True: 
            market_status_list = quote_client.get_market_status(Market.US)
            print(market_status_list)
            if market_status_list[0].status == 'Trading':
                trade(account)
                break
            time.sleep(60)
    elif sys.argv[1] == 'all_off':
    #get_price(95)
    #trade()
    #get_curset(client_config.paper_account)
        all_off(account)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

老虎证券美股策略——将动量策略日频调仓改成月频 的相关文章

  • 乘积怎么表示_三个连续自然数的和等于它们的乘积,求这三个数

    咋一看题目 还是不难 结果全班45人 只有2人写出解答过程 什么题 答案都能凑得出来 写不了过程 我们一起来看看这道五年级数学题 若a b c为三个连续自然数 且满足a b c abc 这三个自然数分别是多少 请写出解题过程 分析 这道题目
  • 7-3 打印沙漏

    7 3 打印沙漏 本题要求你写个程序把给定的符号打印成沙漏的形状 例如给定17个 要求按下列格式打印 所谓 沙漏形状 是指每行输出奇数个符号 各行符号中心对齐 相邻两行符号数差2 符号数先从大到小顺序递减到1 再从小到大顺序递增 首尾符号数
  • mybatis是如何集成到spring的之SqlSessionFactoryBean

    文章目录 1 前言 1 1 集成spring前使用mybatis的方式 1 2 集成mybatis到spring的关键步骤 2 SqlSessionFactoryBean对象分析 2 1 buildSqlSessionFactory做了什么
  • cmake的-G 参数

    一 介绍 CMake默认根据平台选择一个生成器 通常 默认生成器足以让用户继续构建软件 用户可以使用 G选项覆盖默认生成器 cmake G Ninja cmake help的输出包括一个可供用户选择的生成器列表 注意 生成器名称是区分大小写
  • php mysql 开源中国_国内最常用的PHP+MySql免费CMS网站系统大全

    1 DEDE 这是一款国内开源的cms 作者是一个个人 能做出如此功能的cms 是相当不错的 2007版功能十分强大 希望能改善之前数据量一大 更新静态页就很慢的缺点 因为开源 有较多的玩家和拥护者 非常适合有一定编程基础的站长 2 php
  • 图解循环单链表(含C代码)

    目录 1什么是循环单链表 2好处是什么呢 3操作的差异 4代码 1什么是单向循环链表 单向循环链表对比单链表 其实只有一个地方的差异 那就是 尾结点的指针域不是指向空 而是指向了头结点 使其形成了一个环 2好处是什么呢 链表从链尾到链头很方
  • Windows内核面试题(持续更新,目前完成度30%约1.8万字)

    WINDOWS内核编程问题与答案 1 WDK和SDK的区别是什么 2 WDK全称叫做 3 如何创建WDK程序 4 WinDbg如何连接虚拟机 5 Windows内核符号表的作用 6 如何设置内核符号表与源文件 7 如何设置断点与源码调试 8
  • intel android haxm,使用Intel HAXM为Android模拟器加速,媲美真机

    Intel HAXM Hardware Accelerated Execution Manager 使用基于 Intel R Virtualization Technology VT 的硬件加速 因此需要 CPU 支持 VT 而且仅限于 I
  • 定位技术课程设计-微信小程序校园导游系统

    定位技术课程设计课程设计教学目的课程设计要求课程设计题目原题目拓展内容需求分析原理分析微信小程序API定位原理WIFI指纹定位原理路径规划算法调研详细设计总述主页面介绍学校简介页面介绍导引页面概述导引地图景点列表景点详细介绍页面搜索界面导航
  • 测试下几个网络相册

    1 百度相册外链分享 优点 国内站 速度快 可以批量上传 缺点 右下角会有水印 很是不爽 2 试下Photobucket 免费 无水印
  • 第一次CCF CSP认证体验

    今天是我第一次参加CCF CSP认证 虽然这已经是第十二次CCF认证了 感觉题目有点难欸 前面两道题暴力写完 然后看了第三题 哇 简直难写 第四题看了看 数据1e5条边 不会做 就写了一个暴力 希望能过点数据 第五题感觉像是一个动态规划 完
  • HTML(HBuilder)作业题10- 用户登录(jquery)

    问 简单的用户登录怎么弄 答 1 利用jquery 2 利用if 注释 用鼠标离开区域开始判断 可以自行尝试修改成click单击按钮 HBuilder
  • 【华为OD机试真题 Python】最多等和不相交连续子序

    前言 本专栏将持续更新互联网大厂机试真题 并进行详细的分析与解答 包含完整的代码实现 希望可以帮助到正在努力的你 关于大厂机试流程 面经 面试指导等 如有任何疑问 欢迎联系我 wechat steven moda email nansun0
  • mmdetection常见报错以及解决方案汇总

    目录 1 MMCV 安装相关 1 MMCV 与 MMDetection 的兼容问题 ConvWS is already registered in conv layer AssertionError MMCV xxx is used but
  • MFC之AfxbeginThread 线程 创建、挂起、释放、结束、退出

    MFC之AfxbeginThread 线程 创建 挂起 释放 结束 退出 本文简单阐述了如何使用一个afxbeginthread创建一个线程 两种方法 使用默认设置 使用自主设置参数 以及一些如同 挂起 释放 边界锁等操作 h文件添加声明
  • 简单浅谈 电鱼机的脉宽、频率、占空比

    高频鱼机后级的脉宽 频率 占空比 以上三个参数很重要 它不仅是设计鱼机的主要参数 而且也是输出效果调整的最终目标 根据本人长时间玩高频机的一点点经验现向大家浅谈一下脉宽 频率 占空比与之高频鱼机的设计与最终输出效果的两者密切关系 首先说一下
  • 基于s5pv-210开发板 LCD驱动

    lcd硬件原理 利用液晶制成的显示器称为 LCD 依据驱动方式可分为静态驱动 简单矩阵驱动以及主动矩阵驱动 3 种 其中 简单矩阵型又可再细分扭转向列型 TN 和超扭转式向列型 STN 两种 而主动矩阵型则以薄膜式晶体管型 TFT 为主流
  • [深入研究4G/5G/6G专题-50]: URLLC-16-《3GPP URLLC相关协议、规范、技术原理深度解读》-10-高可靠性技术-1-低编码率编码调制方案MCS与高可靠性DRB

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文主页 目录 前言 第1章 什么是MCS 1 1 概念 1 2 MCS针对的对象
  • 转载RAW, YUV, RGB, JPEG之间关系

    RAW格式 从Sensor端最初获取的数字格式的数据 又称为Bayer格式 每个像素信息只有RGB中的某个颜色信息 且每4个像素中有2个像素为G信息 1个R信息 1个B信息 即GRBG格式 2M像素Camera以RAW10格式 每个像素10
  • url的讲解

    摘抄博客 什么是URL URL是什么意思 刘宇凡的专栏 CSDN博客 ur是什么意思 什么是URL URL是Uniform Resource Locator的缩写 即统一资源定位系统 也就是我们通常所说的网址 URL是在Internet的W

随机推荐

  • go get: installing executables with ‘go get‘ in module mode is deprecated.

    go get installing executables with go get in module mode is deprecated 问题描述 原因分析 解决方案 参考链接 问题描述 场景描述 执行go get github com
  • 关于CVE-2023-27161 Jellyfin流媒体系统存在SSRF漏洞的学习

    漏洞描述 Jellyfin 直到 v10 7 7 通过组件 Repository 包含服务器端请求伪造 SSRF 此漏洞允许攻击者通过构建的 POST 请求访问网络资源和敏感信息 环境及部署说明 实验环境 Centos 7 试验机器IP地址
  • 诚之和:Python机器学习之逻辑回归

    在机器学习领域中 逻辑回归是一个非常经典的算法 今天小编带来的是一片关于逻辑回归算法的介绍与实现 希望能给各位小伙伴带来一些帮助 一 题目 1 主题 逻辑回归 2 描述 假设你是某大学招生主管 你想根据两次考试的结果决定每个申请者的录取 机
  • 小程序使用mqtt时的问题

    由于业务需求 小程序项目中需使用mqtt 当我像Vue项目一样去使用时却出现了种种问题 归根结底还是因为没有去仔细看文档 因为英文文档实在懒得看 就那么顺其自然的写 结果浪费了一天时间 这里对小程序中使用mqttjs遇到的问题进行总结 mq
  • java获取两个时间之间的所有日期、月份、年份,返回列表

    需求描述 输入开始时间和结束时间 获取时间范围内的所有日期 月份 年份 输入可以为 yyyy MM dd HH mm ss 或者 yyyy MM dd 一 输入开始时间和结束时间 返回时间范围内中的所有日期列表 传入两个时间范围 返回这两个
  • Javascript组件化开发设计思想

    一 引言 项目中经常用web弹层组件 layer 其常见的代码如下 使用的时候很方便 弹窗的宽高 内容 标题 关闭按钮等弹窗的状态我们都可以通过配置参数配置 layer弹层组件用同一套代码来满足不同的弹窗层表现的需求 这便是组件开发的强大之
  • 服务器优化

    Windows Registry Editor Version 5 00 HKEY LOCAL MACHINE SYSTEM CurrentControlSet Services Tcpip Parameters 关闭无效网关的检查 当服务
  • 网站搭建学习 ubuntu(20.04) 无法使用ifconfig命令-解决办法

    想在新装好的ubuntu系统上部署django 一开始就遇到了问题 使用ifconfig命令时报错 于是按照提示安装net tools sudo apt install net tools 还是有报错 总之先按照系统提示来 用apt get
  • 如何终止一个无限循环线程和 程序退出时销毁线程

    http zhidao baidu com question 299079849 html android 启动了一个子线程 这个子线程是一个死循环 不成的打印 Hello 现在要实现点击一个Button 让这个子线程终止 用什么方法啊 s
  • 单相逆变器第四课、F28027最小系统绘画

    今天我们说的是F28027最小系统的绘画 其实我暂时还没有规划后面要用到什么引脚 所以我很任性的把所有GPIO引脚都接出去了 呵呵 先给大家上一个整体的图 看着图片是不是比较小 呵呵 没办法 截图最大的了 我晚点会把原理图和PCB上传到下载
  • VMware15中安装Linux详细教程

    VMware15中安装Linux详细教程 一 搭建VMware环境 1 打开链接 https www vmware com cn html 选择适合自己电脑系统的版本进行下载 2 下载完成后点击文件进行安装 安装界面如图 注 1 安装目录尽
  • 信息安全产品认证

    文章目录 一 引言 二 网络关键设备和网络安全专用产品安全认证证书 2 1 背景 2 2 产品目录 2 3 认证依据标准 2 4 认证机构 2 5 商密产品检测认证目录 与 网络关键设备和网络安全专用产品目录 的关系 三 中国国家信息安全产
  • 20个常见的Java错误以及规避方法

    原文 50 Common Java Errors and How to Avoid Them Part 1 作者 Angela Stringfellow 翻译 雁惊寒 译者注 本文介绍了20个常见的Java编译器错误 每种错误都包含了代码片
  • MKP勒索病毒:了解最新变种mkp,以及如何保护您的数据

    导言 在数字化时代 mkp 勒索病毒成为了网络安全领域的一大威胁 它采用高级加密技术 将您的数据文件锁定 要求支付赎金以解锁 本文将详细介绍 mkp 勒索病毒的工作原理 如何恢复被它加密的数据文件 以及如何采取预防措施来降低受攻击的风险 如
  • lambdaQuery用法

    lambdaQuery用法 LambdaQueryWrapper
  • pandas DataFrame行或列的删除方法

    pandas DataFrame的增删查改总结系列文章 pandas DaFrame的创建方法 pandas DataFrame的查询方法 pandas DataFrame行或列的删除方法 pandas DataFrame的修改方法 此文我
  • uniapp之微信小程序开发教程及如何合理使用WebSocket(实时监听)+workman聊天系统+linux系统配置阿里云端口

    添加链接描述 添加链接描述 thinphp6 1 workerman文档 添加链接描述 https www kancloud cn manual thinkphp6 0 1147857 workerman手册 https www worke
  • 软件的最低测试方法

    前言 1 1 引言 对于大部分软件系统 如何测试及有效的测试 是一个很头痛的问题 在软件工程上 测试是软件工程中极其重要的一部分 但在具体的实际情况上 无论是时间 人手及资源的调配等原因 使国内大部分软件公司没有进行过理论上的完整的测试 本
  • JAVA变量与数据类型

    人生不如意之事十有八九 在最好的年纪要努力充实自己 莫等空悲切白了少年头 而是要及时当勉励 岁月不待人 一 java变量 变量概述 1 内存中存储的一个存储区域 2 该存储区域内的数据在同一类型范围内不断变化 3 变量是程序中最基本的存储单
  • 老虎证券美股策略——将动量策略日频调仓改成月频

    最近策略频繁回撤 跑不赢标普500指数 所以对策略简单修改 以待后效 新加入的代码 def get if trade day infile open countday dat r incontent infile read infile c