输出问题计算移动平均线

时间:2014-05-12 20:50:14

标签: list python-3.x

我编写了一个函数,在给定日期和价格列表的情况下计算股票的移动平均线。但输出不正确。我只需要第二眼看代码。这是我的代码。

def calculate(self, stock_date_price_list, min_days=2):
    '''Calculates the moving average and generates a signal strategy for buy or sell
       strategy given a list of stock date and price. '''

    stock_averages = []
    stock_signals  = []
    price_list   = [float(n) for n in stock_date_price_list[1::2]]
    days_window   = collections.deque(maxlen=min_days)
    rounding_point = 0.01

    for price in price_list:
        days_window.append(price)
        stock_averages.append(0)
        stock_signals.append("")
        if len(days_window) == min_days:
            moving_avg = sum(days_window) / min_days
            stock_averages[-1] = moving_avg
            if price < moving_avg:
                stock_signals[-1] = "SELL"
            elif price > moving_avg:
                if price_list[-2] < stock_averages[-2]:
                    stock_signals[-1] = "BUY"

    stock_averages[:] = ("%.2f" % avg if abs(avg)>=rounding_point else ' '  for avg in stock_averages)

    return stock_averages, stock_signals

输入是以下列格式的股票价格和日期列表:

 [2012-10-10,52.30,2012-10-09,51.60]

我得到的输出是:

 2012-10-01      659.39                                              
 2012-10-02      661.31                                              
 2012-10-03      671.45                                              
 2012-10-04      666.80                                              
 2012-10-05      652.59                                              
 2012-10-08      638.17                                              
 2012-10-09      635.85                                              
 2012-10-10      640.91                                              
 2012-10-11      628.10                                              
 2012-10-12      629.71         648.43           SELL                
 2012-10-15      634.76         645.97           SELL                
 2012-10-16      649.79         644.81           BUY                    
 2012-10-17      644.61         642.13           BUY                 
 2012-10-18      632.64         638.71           SELL                
 2012-10-19      609.84         634.44           SELL                
 2012-10-22      634.03         634.02           BUY                   
 2012-10-23      613.36         631.77           SELL                
 2012-10-24      616.83         629.37           SELL                

它应该是:

2012-10-01      659.39                                              
2012-10-02      661.31                                              
2012-10-03      671.45                                              
2012-10-04      666.80                                              
2012-10-05      652.59                                              
2012-10-08      638.17                                              
2012-10-09      635.85                                              
2012-10-10      640.91                                              
2012-10-11      628.10                                              
2012-10-12      629.71         648.43                           
2012-10-15      634.76         645.97                           
2012-10-16      649.79         644.81           BUY                    
2012-10-17      644.61         642.13                              
2012-10-18      632.64         638.71           SELL                
2012-10-19      609.84         634.44                           
2012-10-22      634.03         634.02           BUY                    
2012-10-23      613.36         631.77           SELL                
2012-10-24      616.83         629.37           

买卖参数:

如果特定日的收盘价超过简单移动平均线(即当天的收盘价高于当天的简单移动平均线,而前一个收盘价不高于之前的收盘价)移动平均线),产生买入信号。

如果某一天的收盘价低于简单移动平均线,则产生卖出信号。

否则,不产生信号。

1 个答案:

答案 0 :(得分:1)

正如您所说,购买的条件不仅仅是 price > moving_avg也是previous_price < previous_moving_avg。 您可以使用

解决此问题
price_list[-2] < stock_averages[-2]

除了price_list是一个大列表,price_list[-2]始终是大列表中的倒数第二项。它不一定是相对于您在循环中的位置的先前价格。

同样,销售信号不仅需要price < moving_avg,还需要previous_price > previous_moving_avg


calculate还有其他(主要是文体)问题。

  • stock_data_price_list是必需的输入,但您只能使用 切片stock_data_price_list[1::2]。如果是这种情况,您应该要求切片作为输入,而不是stock_data_price_list
  • price_list基本上是这个切片,除了你调用float 在每个项目上。这意味着数据尚未正确解析。 不要让calculate既是数据解析器又是数据 分析仪。制作简单的功能可以完成一项且只能完成一项任务。
  • 同样,calculate不应该进行格式化 结果:

    stock_averages[:] = ("%.2f" % avg if abs(avg)>=rounding_point else ' '  for avg in stock_averages)
    

以下是使用pandas修复代码的方法:

import pandas as pd

data = [('2012-10-01', 659.38999999999999),
 ('2012-10-02', 661.30999999999995),
 ('2012-10-03', 671.45000000000005),
 ('2012-10-04', 666.79999999999995),
 ('2012-10-05', 652.59000000000003),
 ('2012-10-08', 638.16999999999996),
 ('2012-10-09', 635.85000000000002),
 ('2012-10-10', 640.90999999999997),
 ('2012-10-11', 628.10000000000002),
 ('2012-10-12', 629.71000000000004),
 ('2012-10-15', 634.75999999999999),
 ('2012-10-16', 649.78999999999996),
 ('2012-10-17', 644.61000000000001),
 ('2012-10-18', 632.63999999999999),
 ('2012-10-19', 609.84000000000003),
 ('2012-10-22', 634.02999999999997),
 ('2012-10-23', 613.36000000000001),
 ('2012-10-24', 616.83000000000004)]

df = pd.DataFrame(data, columns=['date','price'])
df['average'] = pd.rolling_mean(df['price'], 10)
df['prev_price'] = df['price'].shift(1)
df['prev_average'] = df['average'].shift(1)
df['signal'] = ''
buys = (df['price']>df['average']) & (df['prev_price']<df['prev_average'])
sells = (df['price']<df['average']) & (df['prev_price']>df['prev_average'])
df.loc[buys, 'signal'] = 'BUY'
df.loc[sells, 'signal'] = 'SELL'

print(df)

产量

          date   price  average  prev_price  prev_average signal
0   2012-10-01  659.39      NaN         NaN           NaN       
1   2012-10-02  661.31      NaN      659.39           NaN       
2   2012-10-03  671.45      NaN      661.31           NaN       
3   2012-10-04  666.80      NaN      671.45           NaN       
4   2012-10-05  652.59      NaN      666.80           NaN       
5   2012-10-08  638.17      NaN      652.59           NaN       
6   2012-10-09  635.85      NaN      638.17           NaN       
7   2012-10-10  640.91      NaN      635.85           NaN       
8   2012-10-11  628.10      NaN      640.91           NaN       
9   2012-10-12  629.71  648.428      628.10           NaN       
10  2012-10-15  634.76  645.965      629.71       648.428       
11  2012-10-16  649.79  644.813      634.76       645.965    BUY
12  2012-10-17  644.61  642.129      649.79       644.813       
13  2012-10-18  632.64  638.713      644.61       642.129   SELL
14  2012-10-19  609.84  634.438      632.64       638.713       
15  2012-10-22  634.03  634.024      609.84       634.438    BUY
16  2012-10-23  613.36  631.775      634.03       634.024   SELL
17  2012-10-24  616.83  629.367      613.36       631.775       

[18 rows x 6 columns]

没有熊猫,你可以这样做:

nan = float('nan')

def calculate(prices, size=2):
    '''Calculates the moving average and generates a signal strategy for buy or sell
       strategy given a list of stock date and price. '''

    averages = [nan]*(size-1) + moving_average(prices, size)
    previous_prices = ([nan] + prices)[:-1]
    previous_averages = ([nan] + averages)[:-1]

    signal = []
    for price, ave, prev_price, prev_ave in zip(
        prices, averages, previous_prices, previous_averages):
        if price > ave and prev_price < prev_ave:
            signal.append('BUY')
        elif price < ave and prev_price > prev_ave:
            signal.append('SELL')
        else:
            signal.append('')
    return averages, signal


def window(seq, n=2):
    """
    Returns a sliding window (of width n) over data from the sequence
    s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...
    """
    for i in xrange(len(seq) - n + 1):
        yield tuple(seq[i:i + n])


def moving_average(data, size):
    return [(sum(grp)/len(grp)) for grp in window(data, n=size)]

def report(*args):
    for row in zip(*args):
        print(''.join(map('{:>10}'.format, row)))

dates = ['2012-10-01',
 '2012-10-02',
 '2012-10-03',
 '2012-10-04',
 '2012-10-05',
 '2012-10-08',
 '2012-10-09',
 '2012-10-10',
 '2012-10-11',
 '2012-10-12',
 '2012-10-15',
 '2012-10-16',
 '2012-10-17',
 '2012-10-18',
 '2012-10-19',
 '2012-10-22',
 '2012-10-23',
 '2012-10-24']

prices = [659.38999999999999,
        661.30999999999995,
        671.45000000000005,
        666.79999999999995,
        652.59000000000003,
        638.16999999999996,
        635.85000000000002,
        640.90999999999997,
        628.10000000000002,
        629.71000000000004,
        634.75999999999999,
        649.78999999999996,
        644.61000000000001,
        632.63999999999999,
        609.84000000000003,
        634.02999999999997,
        613.36000000000001,
        616.83000000000004]

averages, signals = calculate(prices, size=10)
report(dates, prices, averages, signals)

产生

2012-10-01    659.39       nan          
2012-10-02    661.31       nan          
2012-10-03    671.45       nan          
2012-10-04     666.8       nan          
2012-10-05    652.59       nan          
2012-10-08    638.17       nan          
2012-10-09    635.85       nan          
2012-10-10    640.91       nan          
2012-10-11     628.1       nan          
2012-10-12    629.71   648.428          
2012-10-15    634.76   645.965          
2012-10-16    649.79   644.813       BUY
2012-10-17    644.61   642.129          
2012-10-18    632.64   638.713      SELL
2012-10-19    609.84   634.438          
2012-10-22    634.03   634.024       BUY
2012-10-23    613.36   631.775      SELL
2012-10-24    616.83   629.367