python测试多空交易效果代码

来源:互联网 发布:怎么在淘宝上做充值 编辑:程序博客网 时间:2024/06/01 16:06

用python写了一个简单的多空交易的测试代码

其中的空头部分用分级基金A,多头部分用跟踪同样指数的etf基金

测试的不是很理想。

由于刚开始接触python,所以在编写代码时已实现功能为主,还有很多可以改进的地方。十分欢迎有相同爱好的朋友一起交流。代码如下

from __future__ import division
import tushare as ts
import pandas as pd
import numpy as np
import csv

init_money=100000     

def file2data(filename):        #将文件中的历史数据以一个列表的形式返回
        str_filename="../data/"+filename
        f=open(str_filename)    #打开文件
        lines=f.readlines()     #读取文件中的所有行
        lst=[]                  #一个空的列表,用于存储文件数据
        i=0
        for line in lines:
                if i==0:        #跳过第一行
                        i+=1
                        continue
                else:
                        lst.append(line)

        f.close()
        return lst      #返回数据

def equalData(filename):        #将两个投资标的的历史数据进行等长化处理,filename用于一个列表数据更好
        lst=[]                  #空列表用于存储各标的的历史数据
        lens=[]                 #空列表用于存储各标的历史数据的长度
        for i in range(len(filename)):
                lst.append(file2data(filename[i]))
                lens.append(len(lst[i]))

        #此时lst为一个二维列表,两个元素,每一个元素为对应投资标的的历史数据
        if lens[0]==lens[1]:    #如果长度相等,则返回两个列表,分别对应各自的历史数据
                return lst[0],lst[1]
        elif lens[0]<lens[1]:   #表示投资标的0晚于投资标的1上市,所以以标的0为准进行等长化处理
                data=lst[1][:lens[0]]
                return lst[0],data
        else:
                data=lst[0][:lens[1]]
                return data,lst[1]

def reverseData(hist_data):     #按照时间顺序重新排列数据(由远及近)
        data=hist_data[::-1]
        return data

def initOrder(data1,data2):     #建仓函数,用于第一次交易,返回两个投资标的的持仓数
        money_for_target1=money_for_target2=init_money*0.5      #可以用在单一标的上的资金

        data1_list=str2list(data1[0])                                   #将字符串类型的历史数据转换为列表类型
        data2_list=str2list(data2[0])

        price_target1=float(data1_list[3])                              #将字符串类型的收盘价转换为整数类型
        price_target2=float(data2_list[3])

        share_for_target1=round(money_for_target1/price_target1,0)
        share_for_target1=share_for_target1-share_for_target1%100       #确保持仓数为100的整数倍
        share_for_target2=round(money_for_target2/price_target2,0)
        share_for_target2=share_for_target2-share_for_target2%100
        remain_money=init_money-price_target1*share_for_target1-price_target2*share_for_target2
        return data1_list[0],share_for_target1,float(data1_list[3]),share_for_target2,float(data2_list[3]),remain_money

def str2list(data):     #因为历史数据中的每一行都是以字符串格式存储,所以需要将每一行的历史数据换成列表形式
        list_data=data.split(',')
        return list_data

def rebalance(sum_money,price_for_short,price_for_bull):
#仓位再平衡函数,将仓位重新回到50-50
#输入参数:当前总价值、空头部分单价、多头部分单价
#输出参数:再平衡后的空头部分持股,多头部分持股数,现金余额
        money_for_short=money_for_bull=sum_money*0.5      #可以用在单一标的上的资金

        share_for_short=round(money_for_short/price_for_short,0)
        share_for_short=share_for_short-share_for_short%100

        share_for_bull=round(money_for_bull/price_for_bull,0)
        share_for_bull=share_for_bull-share_for_bull%100

        remain_money=sum_money-price_for_short*share_for_short-price_for_short*share_for_short
        return share_for_short,share_for_bull,remain_money

def is_year_first_tradeday(data):       #判断是否为一年的第一个交易日,为简化模型,分级A的折算在第一个交易日进行
#输入参数为转换后的历史数据(即以时间为标准由远及近排列)
#判断依据为前后两条数据的年份不同,则后一条数据即为当年的第一个交易日
#返回参数为一个列表,用于存储所有历史数据中的第一个年度交易日
        year_first_record=data[0][0:4]  #第一条历史记录的年份
        year_previous_record=year_first_record  #前一条历史记录的年份

        year_list=[]
        for i in range(len(data)-1):
                year_current_record=data[i+1][0:4]
                if year_current_record==year_previous_record:
                        year_previous_record=year_current_record
                        #continue
                else:
                        year_list.append(data[i+1][0:10])
                        year_previous_record=year_current_record

        return year_list

def experiment_test(file_list):
#该函数用于测试策略效果
#读取数据文件
#进行第一次初始化交易
#每个交易日用收盘价
#如果符合条件则在后一个交易日用收盘价进行再平衡
#判断这个交易日是否是当年的第一个交易日,如果是第一个交易日则进行再平衡

#输入参数为数据文件列表

        data1,data2=equalData(file_list)        #data_short表示空头数据, data_bull表示多头数据
        data_short=reverseData(data1)   #按照时间反序排列
        data_bull=reverseData(data2)
        date="" #交易日期
        share_for_short=0       #空头份额
        share_for_bull=0        #多头份额
        remain_money=0          #剩余金额
        sum_money=0             #总市值
        year_list=is_year_first_tradeday(data_short)    #用于找出回测期间内每年的第一个交易日
        #开始进行第一次交易,即初始化建仓交易
        date,share_for_short,init_short_price,share_for_bull,init_bull_price,remain_money=initOrder(data_short,data_bull)
        sum_money=share_for_short*init_short_price+share_for_bull*init_bull_price+remain_money
        print "the trade_date is %s,the hold share for short is %d,the hold share for bull is %d,the remain money is %f, the total value is %d" % (date,share_for_short,share_for_bull,remain_money,sum_money)


        #跳过第一条历史数据
        data_short.pop(0)
        data_bull.pop(0)

        for i in range(len(data_short)):
                date=data_short[i][0:10]        #获取交易日期,此时data_short类表中的每一条历史数据还是以整个字符串为的形式
                #将空头、多头的历史数据均转换成每一个元素都是列表的形式
                pre_list_data_short=str2list(data_short[i])
                pre_list_data_bull=str2list(data_bull[i])
                #获取当天两个标的的收盘价               
                price_for_short=float(pre_list_data_short[4])
                price_for_bull=float(pre_list_data_bull[4])

                sum_money=share_for_short*price_for_short+share_for_bull*price_for_bull+remain_money    #当日持仓总市值
                short_value=share_for_short*price_for_short                                             #当日空头部分总市值
                bull_value=share_for_bull*price_for_bull                                                #当日多头部分总市值

                short_part=short_value/sum_money                                                        #分别计算多空占比
                bull_part=bull_value/sum_money

                if abs(short_part-bull_part)>0.4:       #即有一部分的仓位占比超过了70%,需要开始进行再平衡操作
                        share_for_short,share_for_bull,remain_monry=rebalance(sum_money,price_for_short,price_for_bull)
                        print "%s rebalance" % date
                elif (date in year_list):       #如果是每年的第一个交易日,则进行定折
                        print "fist"
                        short_real_value=share_for_short*1.004  #按照4%的收益率进行折算
                        bull_real_value=share_for_bull*price_for_bull   #计算多头部分的市值
                        sum_money=real_sum_money=short_real_value+bull_real_value+remain_money  #计算折算后的总市值
                        share_for_short,share_for_bull,remain_monry=rebalance(real_sum_money,price_for_short,price_for_bull)

                print "the trade_date is %s,the hold share for short is %d,the part is %f,the hold share for bull is %d,part is %f,the remain money is %f, the total value is %d" % (date,share_for_short,short_part,share_for_bull,bull_part,remain_money,sum_money)



0 0