zoukankan      html  css  js  c++  java
  • 佐治亚理工学院 计算投资公开课第六周作业 投资策略分析平台

    策略分析平台

    在前两周的工作中,实现了股票价格低于门限值这一策略的event study,即根据门限值来看事件发生前后股票的价格。同时,完成了根据下单的指令来进行回测,计算策略执行期间每一天的价值,以及对投资结果的分析。这一周,要求把这三部分结合起来,能够实现根据门限值直接回测生成过去时间段的下单指令,并进行计算分析。


    工具和方法

    编程工具

    编程语言是python,用到的开源量化分析软件包是 QuantSoftware ToolKit,同时用到numpy和datetime等包。

    Event Study

    Event Study是指对一类事件前后股票的表现进行研究,根据价格变化来确定投资策略。

    可以看到,取事件为股票跌破7美元,取事件前后各二十天股票叠加,2012年的SP500指数股票2008到2009年趋势如上图。很显然,当这一类事件发生后,立即买入,5天后卖出,是一种不错的方案。如果更长时间后卖出,方差更大,风险更大。据此,可以确定下单指令:
    Date, AAPL, BUY, 100
    Date + 5 days, AAPL, SELL, 100
    

    股值计算

    这一部分是相对比较简单的,要从csv格式的文件里面读取指令,执行指令,并计算实际交易期间的资产价值,即持有股票的价格和现金之和。下单指令的顺序并不是按照日期排列的,因此计算时要比较小心。
    这一部分要将生成的日期和对应价值写入csv文件,如下:
    2008,01,03,50000.0
    2008,01,04,49893.0
    2008,01,07,49875.0
    2008,01,08,49846.0
    2008,01,09,49801.0
    2008,01,10,49844.0
    2008,01,11,49844.0
    2008,01,14,49844.0
    
    注意,这个文件仅记录最初买入到最后一次卖出期间的价格。下一步进行策略评估也是根据这些数据来做的。

    策略评估

    这一部分要求根据策略执行期间的资产价值计算总收益率、日均收益率、收益率标准差和Sharp Ratio。
    计算日收益率时,第一天为0,以后每日收益率为相对前一天的增值比率。日均和标准差都是根据日收益率来计算的,是最常用的评估指标。Sharp Ratio是日均收益率和标准差之比进行年化得到,用以衡量收益和风险的比例。
    按照之前所说的时间期限和策略,各参数如下:
    The final value of the portfolio using the sample file is -- 2009,12,28,54824.0
    
    Details of the Performance of the portfolio
    
    Data Range :  2008-01-03 16:00:00  to  2009-12-28 16:00:00
    
    Sharpe Ratio of Fund : 0.527865227084
    Sharpe Ratio of $SPX : -0.184202673931
    
    Total Return of Fund :  1.09648
    Total Return of $SPX : 0.779305674563
    
    Standard Deviation of Fund :  0.0060854156452
    Standard Deviation of $SPX : 0.022004631521
    
    Average Daily Return of Fund :  0.000202354576186
    Average Daily Return of $SPX : -0.000255334653467
    可以看到,与SPX,即标准普尔指数相比,这种投资策略在每个参数上面都有优势,是一种有效的投资策略。

    平台实现

    平台按照上文提到的功能模块划分为三部分。代码如下:

    Event Study实现

    这一部分除了对事件进行展示,还要按照之前提到的规则生成下单指令:
    #how to work? evalate the command below in order
    #execfile('hw4_event.py')
    #execfile('hw4_order.py')
    #execfile('hw4_anylize.py')
    
    #change edge_price to change event
    
    
    import pandas as pd
    import numpy as np
    import math
    import copy
    import QSTK.qstkutil.qsdateutil as du
    import datetime as dt
    import QSTK.qstkutil.DataAccess as da
    import QSTK.qstkutil.tsutil as tsu
    import QSTK.qstkstudy.EventProfiler as ep
    
    def find_events(ls_symbols, d_data):
        ''' Finding the event dataframe '''
        df_close = d_data['actual_close']
        ts_market = df_close['SPY']
    
        print "Finding Events"
        
        #events defined here
        edge_price=7.0
        buy_sell_order=''
    
        # Creating an empty dataframe
        df_events = copy.deepcopy(df_close)
        df_events = df_events * np.NAN
    
        # Time stamps for the event range
        ldt_timestamps = df_close.index
    
        for s_sym in ls_symbols:
            for i in range(1, len(ldt_timestamps)):
                # Calculating the returns for this timestamp
                #f_symprice_today = df_close[s_sym].ix[ldt_timestamps[i]]
                #f_symprice_yest = df_close[s_sym].ix[ldt_timestamps[i - 1]]
                #f_marketprice_today = ts_market.ix[ldt_timestamps[i]]
                #f_marketprice_yest = ts_market.ix[ldt_timestamps[i - 1]]
                #f_symreturn_today = (f_symprice_today / f_symprice_yest) - 1
                #f_marketreturn_today = (f_marketprice_today / f_marketprice_yest) - 1
    
                # Event is found if the symbol is down more then 3% while the
                # market is up more then 2%
                #if f_symreturn_today <= -0.03 and f_marketreturn_today >= 0.02:
                if df_close[s_sym].ix[ldt_timestamps[i-1]]>=edge_price and df_close[s_sym].ix[ldt_timestamps[i]]<edge_price:
                    df_events[s_sym].ix[ldt_timestamps[i]] = 1
                    tmp_time=ldt_timestamps[i]
                    tmp_day=dt.date(tmp_time.year,tmp_time.month,tmp_time.day)
                    buy_sell_order+=str(tmp_day).replace('-',',')+','+s_sym+',Buy,'+str(100)+','
                    if i+5<len(ldt_timestamps):
                        tmp_time=ldt_timestamps[i+5]
                    else:
                        tmp_time=ldt_timestamps[-1]
                    tmp_day=dt.date(tmp_time.year,tmp_time.month,tmp_time.day)
                    buy_sell_order+=str(tmp_day).replace('-',',')+','+s_sym+',Sell,'+str(100)+','
    
        order_list=list(buy_sell_order.split(','))
        del order_list[-1]
        order_array=np.array(order_list)
        order_array.resize((order_array.size/6,6))
        np.savetxt("myorder.csv",order_array,delimiter=',',fmt='%s')
        return df_events
    
    
    if __name__ == '__main__':
        dt_start = dt.datetime(2008, 1, 1)
        dt_end = dt.datetime(2009, 12, 31)
        ldt_timestamps = du.getNYSEdays(dt_start, dt_end, dt.timedelta(hours=16))
    
        dataobj = da.DataAccess('Yahoo')
        ls_symbols = dataobj.get_symbols_from_list('sp5002012')
        ls_symbols.append('SPY')
    
        ls_keys = ['open', 'high', 'low', 'close', 'volume', 'actual_close']
        ldf_data = dataobj.get_data(ldt_timestamps, ls_symbols, ls_keys)
        d_data = dict(zip(ls_keys, ldf_data))
    
        for s_key in ls_keys:
            d_data[s_key] = d_data[s_key].fillna(method='ffill')
            d_data[s_key] = d_data[s_key].fillna(method='bfill')
            d_data[s_key] = d_data[s_key].fillna(1.0)
    
        df_events = find_events(ls_symbols, d_data)
        print "Creating Study"
        ep.eventprofiler(df_events, d_data, i_lookback=20, i_lookforward=20,
                    s_filename='eventstudy.pdf', b_market_neutral=True, b_errorbars=True,
                    s_market_sym='SPY')
    

    股值计算

    下单指令上一个模块已经生成,据此计算资产价值:
    #how to work? evalate the command below in order
    #execfile('hw4_event.py')
    #execfile('hw4_order.py')
    #execfile('hw4_anylize.py')
    
    #change currentCash,dt_start,dt_end
    
    import pandas as pd
    import numpy as np
    import math
    import copy
    import QSTK.qstkutil.qsdateutil as du
    import datetime as dt
    import QSTK.qstkutil.DataAccess as da
    import QSTK.qstkutil.tsutil as tsu
    import QSTK.qstkstudy.EventProfiler as ep
    
    
    #get order
    #sys.argv to get comman parameter
    na_data = np.loadtxt('myorder.csv',dtype=np.str,delimiter=',')
    #dtype={'names':('year','month','day','equity','buorsell','count'),    'formats':('i4','i4','i4','S5','S5','i4')},
    na_dates=np.int_(na_data[:,0:3])
    order=na_data[:,3:6]
    ls_symbols=set(order[:,0])
    
    #get equity price
    dt_start = dt.datetime(2008, 1, 1)
    dt_end = dt.datetime(2009, 12, 31)
    ldt_timestamps = du.getNYSEdays(dt_start, dt_end, dt.timedelta(hours=16))
    
    dataobj = da.DataAccess('Yahoo')
    
    #why close?
    #close for Adjusted Close ;actual_close for actual close
    ls_keys = 'close'#['open', 'high', 'low', 'close', 'volume', 'actual_close']
    ldf_data = dataobj.get_data(ldt_timestamps, ls_symbols, ls_keys)
    
    #calc portfolio
    currentCash=50000
    currentEquity=dict()
    byOrSellDict={'Buy':1,'Sell':-1}
    
    #dateInd=0
    #currentDate=dt.datetime(na_dates[dateInd,0],na_dates[dateInd,1],na_dates[dateInd,2])+dt.timedelta(hours=16)
    #orders=[dt.datetime(na_dates[dateInd,0],na_dates[dateInd,1],na_dates[dateInd,2])+dt.timedelta(hours=16),
    #    [order[dateInd,0],order[dateInd,1],int(order[dateInd,2])] for dateInd in range(na_data.shape[0])]
    orders={}
    for dateInd in range(na_data.shape[0]):
        tmpDate=dt.datetime(na_dates[dateInd,0],na_dates[dateInd,1],na_dates[dateInd,2])+dt.timedelta(hours=16)
        if tmpDate in orders.keys():
            orders[tmpDate].append([order[dateInd,0],order[dateInd,1],int(order[dateInd,2])])
        else:orders[tmpDate]=[[order[dateInd,0],order[dateInd,1],int(order[dateInd,2])]]
    
    #calc first and last day of order
    order_date_list=list(orders.keys())
    order_date_list.sort()
    first_day=order_date_list[0]
    last_day=order_date_list[-1]
    
    values=''
    for i in ldt_timestamps:
        if i<first_day or i>last_day:
            continue
        if i in orders.keys():
            for singleOrder in orders[i]:
                equity=singleOrder[0]
                byOrSell=singleOrder[1]
                count=singleOrder[2]
                if equity in currentEquity.keys():
                    currentEquity[equity]+=count*byOrSellDict[byOrSell]
                else:currentEquity[equity]=count*byOrSellDict[byOrSell]
                currentCash+=-ldf_data[equity][i]*count*byOrSellDict[byOrSell]
        
                print '----------------------',i,equity,byOrSell,count
                print currentEquity
                
                #dateInd+=1
                #currentDate=dt.datetime(na_dates[dateInd,0],na_dates[dateInd,1],na_dates[dateInd,2])+dt.timedelta(hours=16)
        
        #calc portfolia value
        portfValue=currentCash
        for tmpEqui in currentEquity.keys():
            portfValue+=ldf_data[tmpEqui][i]*currentEquity[tmpEqui]
        print i,portfValue
        values+=str(dt.date(i.year,i.month,i.day)).replace('-',',')+','+str(portfValue)+','
        
    values_list=list(values.split(','))
    del values_list[-1]
    values_array=np.array(values_list)
    values_array.resize((values_array.size/4,4))
    np.savetxt("hw4values.csv",values_array,delimiter=',',fmt='%s')
    

    策略评估

    根据上一模块生成了日期--价值文件计算策略的各种指标:
    #how to work? evalate the command below in order
    #execfile('hw4_event.py')
    #execfile('hw4_order.py')
    #execfile('hw4_anylize.py')
    
    from math import sqrt
    
    date_values = np.loadtxt('hw4values.csv',dtype=np.str,delimiter=',')
    values=np.float_(date_values[:,3])
    
    total_return=values[-1]/values[0]
    
    #dayly_return=values[1:]/values[:-1]-1
    dayly_return=tsu.returnize0(values)
    
    std=np.std(dayly_return)
    
    ave_dayly_ret=np.mean(dayly_return)
    
    sharp_ratio=ave_dayly_ret/std*sqrt(252)
    
    print 'Total Return of Fund: ',total_return
    print 'Standard Deviation of Fund: ',std
    print 'Average Daily Return of Fund: ',ave_dayly_ret
    print 'Sharpe Ratio of Fund: ',sharp_ratio

    平台整合

    顺序执行上述三个文件即可得到策略的各种指标,完成策略的回测:
    execfile('hw4_event.py')
    execfile('hw4_order.py')
    execfile('hw4_anylize.py')
    





  • 相关阅读:
    网站实时信息采集和统计graphite
    内存检查工具Valgrind
    usr/bin/ld: cannot find 错误解决方法和 /etc/ld.so.conf
    通用makefile
    关于/proc/进程idpid/fd ,根据fd来查找连接
    boost enable_shared_from_this
    cdll和windll的差别
    一些项目——空白格式化
    Session笔记
    黑马程序猿_7K面试题之交通灯系统
  • 原文地址:https://www.cnblogs.com/suncoolcat/p/3367793.html
Copyright © 2011-2022 走看看