1

So I am trying to get multiple stock prices using pandas and panadas datareader. If I only try to import one ticker it will run fine, but if I use more than one then an error arises. The code is:

import pandas as pd
import pandas_datareader as web
import datetime as dt
stocks = ['BA', 'AMD']
start = dt.datetime(2018, 1, 1)
end = dt.datetime(2020, 1, 1)
d = web.DataReader(stocks, 'yahoo', start, end) 

Though I get the error:

ValueError: Wrong number of items passed 2, placement implies 1

So how do I get around it only allowing to pass 1 stock. So far I have tried using quandl and google instead, which dont work either. I also have tried pdr.get_data_yahoo but I get the same result. I have also tried yf.download() and still get the same issue. Does anyone have any ideas to get around this? Thank you.

EDIT: Full code:

import pandas as pd
import pandas_datareader as web
import datetime as dt
import yfinance as yf
import numpy as np
stocks = ['BA', 'AMD', 'AAPL']
start = dt.datetime(2018, 1, 1)
end = dt.datetime(2020, 1, 1)
d = web.DataReader(stocks, 'yahoo', start, end)
d['sma50'] = np.round(d['Close'].rolling(window=2).mean(), decimals=2)
d['sma200'] = np.round(d['Close'].rolling(window=14).mean(), decimals=2)
d['200-50'] = d['sma200'] - d['sma50']
_buy = -2
d['Crossover_Long'] = np.where(d['200-50'] < _buy, 1, 0)
d['Crossover_Long_Change']=d.Crossover_Long.diff()
d['buy'] = np.where(d['Crossover_Long_Change'] == 1, 'buy', 'n/a')
d['sell'] = np.where(d['Crossover_Long_Change'] == -1, 'sell', 'n/a')
pd.set_option('display.max_rows', 5093)
d.drop(['High', 'Low', 'Close', 'Volume', 'Open'], axis=1, inplace=True)
d.dropna(inplace=True)
#make 2 dataframe
d.set_index(d['Adj Close'], inplace=True)
buy_price = d.index[d['Crossover_Long_Change']==1]
sell_price = d.index[d['Crossover_Long_Change']==-1]
d['Crossover_Long_Change'].value_counts()
profit_loss = (sell_price - buy_price)*10
commision = buy_price*.01
position_value = (buy_price + commision)*10
percent_return = (profit_loss/position_value)*100
percent_rounded = np.round(percent_return, decimals=2)
prices = { 
    "Buy Price" : buy_price,
    "Sell Price" : sell_price,
    "P/L" : profit_loss,
    "Return": percent_rounded
}
df = pd.DataFrame(prices)
print('The return was {}%, and profit or loss was ${} '.format(np.round(df['Return'].sum(), decimals=2), 
                                                               np.round(df['P/L'].sum(), decimals=2)))
d
Sajan
  • 1,247
  • 1
  • 5
  • 13
Bentio cano
  • 53
  • 1
  • 6
  • Does this answer your question? [Downloading mutliple stocks at once from yahoo finance python](https://stackoverflow.com/questions/49705047/downloading-mutliple-stocks-at-once-from-yahoo-finance-python) – Trenton McKinney May 25 '20 at 18:59
  • @Trenton McKinney Thank you for responding, I have already seen that page and I tried that but then I still received the same error that I couldn't pass 2 objects through. – Bentio cano May 25 '20 at 19:01
  • Sorry i don't understand the question - aren't you passing 2 stocks ['BA', 'AMD'] and isn't this code working? – NYC Coder May 25 '20 at 19:04

3 Answers3

0

I tried 3 stocks in your code and it returns data for all 3, not sure I understood the problem you're facing?

import pandas as pd
import pandas_datareader as web
import datetime as dt
stocks = ['BA', 'AMD', 'AAPL']
start = dt.datetime(2018, 1, 1)
end = dt.datetime(2020, 1, 1)
d = web.DataReader(stocks, 'yahoo', start, end)
print(d)

Output:

Attributes   Adj Close                              Close                         ...        Open                            Volume
Symbols             BA        AMD        AAPL          BA        AMD        AAPL  ...          BA        AMD        AAPL         BA          AMD        AAPL
Date                                                                              ...
2018-01-02  282.886383  10.980000  166.353714  296.839996  10.980000  172.259995  ...  295.750000  10.420000  170.160004  2978900.0   44146300.0  25555900.0
2018-01-03  283.801239  11.550000  166.324722  297.799988  11.550000  172.229996  ...  295.940002  11.610000  172.529999  3211200.0  154066700.0  29517900.0
2018-01-04  282.724396  12.120000  167.097290  296.670013  12.120000  173.029999  ...  297.940002  12.100000  172.539993  4171700.0  109503000.0  22434600.0
2018-01-05  294.322296  11.880000  168.999741  308.839996  11.880000  175.000000  ...  296.769989  12.190000  173.440002  6177700.0   63808900.0  23660000.0
2018-01-08  295.570740  12.280000  168.372040  310.149994  12.280000  174.350006  ...  308.660004  12.010000  174.350006  4124900.0   63346000.0  20567800.0
...                ...        ...         ...         ...        ...         ...  ...         ...        ...         ...        ...          ...         ...
2019-12-24  331.030457  46.540001  282.831299  333.000000  46.540001  284.269989  ...  339.510010  46.099998  284.690002  4120100.0   44432200.0  12119700.0
2019-12-26  327.968689  46.630001  288.442780  329.920013  46.630001  289.910004  ...  332.700012  46.990002  284.820007  4593400.0   57562800.0  23280300.0
2019-12-27  328.187408  46.180000  288.333313  330.140015  46.180000  289.799988  ...  330.200012  46.849998  291.119995  4124000.0   36581300.0  36566500.0
2019-12-30  324.469513  45.520000  290.044617  326.399994  45.520000  291.519989  ...  330.500000  46.139999  289.459991  4525500.0   41149700.0  36028600.0
2019-12-31  323.833313  45.860001  292.163818  325.760010  45.860001  293.649994  ...  325.410004  45.070000  289.929993  4958800.0   31673200.0  25201400.0
NYC Coder
  • 7,424
  • 2
  • 11
  • 24
  • I tried the code above and received the same error. The error that I received has been added to the question as an edit. – Bentio cano May 25 '20 at 19:14
  • Can you try `pip install pandas_datareader --upgrade` and the same for pandas. What version of python and pandas are you using? – NYC Coder May 25 '20 at 19:18
  • I have already tried doing this, and my pandas and my pandas datareader version is 1.14.0 . I am using python 3.7 – Bentio cano May 25 '20 at 19:23
  • Where are you running this code? Can you try running it somewhere else? Like python terminal or Jupyter? – NYC Coder May 25 '20 at 19:25
  • I am running it in Jupyter – Bentio cano May 25 '20 at 19:27
  • Try running it on vscode or python terminal and see if you get the same error – NYC Coder May 25 '20 at 19:28
  • 1
    So it seems that when I just request for the data then it prints the output you have above. But then it gives the error that I cant pass 3 arguments in 1 when I run it with the full code (it is printed above). I have run the full code with just one company and it works fine. But then when I pass 2 or more then it gives me the error. Do you have any ideas as to why this is? – Bentio cano May 25 '20 at 19:35
0

I think the error comes from your moving average and the line d['sma50'] = np.round(d['Close'].rolling(window=2).mean(), decimals=2) because d represent 3 stocks, I think you have to separate each stock and compute the moving average separately

EDIT : I tried something for two stocks only (BA and AMD) but it is not the best solution because I'm always repeating myself for every line. I'm just a beginner in Python but maybe this will help you to find a solution to your problem PS : The last line doesn't work really well (which is the printing of the P&L and Return)

"

import pandas as pd
import pandas_datareader as web
import datetime as dt
stock1 = ['BA']
stock2=['AMD']
start = dt.datetime(2018, 1, 1)
end = dt.datetime(2020, 1, 1)
d1 = web.DataReader(stock1, 'yahoo', start, end)
d2 = web.DataReader(stock2, 'yahoo', start, end)
d1['sma50'] = np.round(d1['Close'].rolling(window=2).mean(), decimals=2)
d2['sma50'] = np.round(d2['Close'].rolling(window=2).mean(), decimals=2)
d1['sma200'] = np.round(d1['Close'].rolling(window=14).mean(), decimals=2)
d2['sma200'] = np.round(d2['Close'].rolling(window=14).mean(), decimals=2)
d1['200-50'] = d1['sma200'] - d1['sma50']
d2['200-50'] = d2['sma200'] - d2['sma50']
_buy = -2
d1['Crossover_Long'] = np.where(d1['200-50'] < _buy, 1, 0)
d2['Crossover_Long'] = np.where(d2['200-50'] < _buy, 1, 0)
d1['Crossover_Long_Change']=d1.Crossover_Long.diff()
d2['Crossover_Long_Change']=d2.Crossover_Long.diff()
d1['buy'] = np.where(d1['Crossover_Long_Change'] == 1, 'buy', 'n/a')
d2['buy'] = np.where(d2['Crossover_Long_Change'] == 1, 'buy', 'n/a')
d1['sell_BA'] = np.where(d1['Crossover_Long_Change'] == -1, 'sell', 'n/a')
d2['sell_AMD'] = np.where(d2['Crossover_Long_Change'] == -1, 'sell', 'n/a')
pd.set_option('display.max_rows', 5093)
d1.drop(['High', 'Low', 'Close', 'Volume', 'Open'], axis=1, inplace=True)
d2.drop(['High', 'Low', 'Close', 'Volume', 'Open'], axis=1, inplace=True)
d2.dropna(inplace=True)
d1.dropna(inplace=True)
d1.set_index("Adj Close",inplace=True)
d2.set_index("Adj Close",inplace=True)
buy_price_BA = np.array(d1.index[d1['Crossover_Long_Change']==1])
buy_price_AMD = np.array(d2.index[d2['Crossover_Long_Change']==1])
sell_price_BA = np.array(d1.index[d1['Crossover_Long_Change']==-1])
sell_price_AMD = np.array(d2.index[d2['Crossover_Long_Change']==-1])
d1['Crossover_Long_Change'].value_counts()
d2['Crossover_Long_Change'].value_counts()
profit_loss_BA = (sell_price_BA - buy_price_BA)*10
profit_loss_AMD = (sell_price_AMD - buy_price_AMD)*10
commision_BA = buy_price_BA*.01
commision_AMD = buy_price_AMD*.01
position_value_BA = (buy_price_BA + commision_BA)*10
position_value_AMD = (buy_price_AMD + commision_AMD)*10
percent_return_BA = np.round(((profit_loss_BA/position_value_BA)*100),decimals=2)
percent_return_AMD = np.round(((profit_loss_AMD/position_value_AMD)*100),decimals=2)
prices_BA = { 
    "Buy Price BA" : [buy_price_BA],
    "Sell Price BA" : [sell_price_BA],
    "P/L BA" : [profit_loss_BA],
    "Return BA": [percent_return_BA]}
df = pd.DataFrame(prices_BA)
print('The return was {}%, and profit or loss was ${} '.format(np.round(df['Return BA'].sum(), decimals=2), 
                                                           np.round(df['P/L BA'].sum(), decimals=2)))
prices_AMD = { 
    "Buy Price AMD" : [buy_price_AMD],
    "Sell Price AMD" : [sell_price_AMD],
    "P/L AMD" : [profit_loss_AMD],
    "Return AMD": [percent_return_AMD]}
df = pd.DataFrame(prices_AMD)
print('The return was {}%, and profit or loss was ${} '.format(np.round(df['Return AMD'].sum(), decimals=2), 
                                                               np.round(df['P/L AMD'].sum(), decimals=2)))
Kben59
  • 378
  • 2
  • 10
  • Thank you for responding. I was thinking this too, but how would I adjust the code for the moving averages for them to sperate. – Bentio cano May 25 '20 at 19:58
  • Would I have to rewrite the entire code for each stock? – Bentio cano May 25 '20 at 20:02
  • I've added an edit. I tried to run your code with just one stock but I add errors, you can look at my code and if ever you find a solution could you please post the code here ? It will help improving my coding skills. Thank you – Kben59 May 26 '20 at 13:20
0

It seems like there's a bug in the pandas data reader. I work around it by initialising with one symbol and then setting the symbols property on the instantiated object. After doing that, it works fine to call read() on tmp below.

import pandas_datareader as pdr
all_symbols = ['ibb', 'xly', 'fb', 'exx1.de']

tmp = pdr.yahoo.daily.YahooDailyReader(symbols=all_symbols[0])
# this is a work-around, pdr is broken...
tmp.symbols = all_symbols
data = tmp.read()
Lars Larsson
  • 566
  • 5
  • 10