2014-05-12 54 views
0

我編寫了一個函數,該函數根據日期和價格列表計算股票的移動平均線。但輸出不正確。我只需要第二組代碼。這是我的代碼。計算移動平均線的輸出問題

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   

buyi的參數ng/selling:

如果特定日期的收盤價高於簡單移動平均線(即當日收盤價高於當天的簡單移動平均值,而前一收盤價不高於先前收盤價簡單移動均線),產生買入信號。

如果特定日期的收盤價低於簡單移動平均線,則產生賣出信號。

否則,不生成信號。

+0

什麼是你打印有值是多少?有些代碼可以工作嗎?如果將買入/賣出信號的計算分解爲一個函數,將單個價格的所有相關值分開,則可能會更容易,因此您可以單獨對其進行測試。 – jonrsharpe

+0

@jonrsharpe打印的價值是日期,收盤價格,移動平均線,買/賣決定..代碼似乎沒有問題,除了輸出。我一直在試圖把它分成兩個功能,但是因爲我對這個新手並沒有太多的運氣。 – user3233949

回答

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   
+0

我不允許使用熊貓圖書館。有沒有糾正price_list [-2] user3233949

+0

我們可以將信號分離成單獨的函數嗎? – user3233949

+0

甚至是一個單獨的課程? – user3233949