Value Error: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all()

Viewed 909

I have written a python application which allows me to buy and sell stocks using the zerodha platform. Now when I buy the stocks I want to sell these if the values of the close_price < exit_price. The exit_price is calculated as exit_price = (close_price*0.91)

Here is my code:

from kiteconnect import KiteConnect
import os
import pandas as pd
import openpyxl

cwd = os.chdir("C:/Users/Administrator/Desktop/Zerodha")

#generate trading session
access_token = open("access_token.txt",'r').read()
key_secret = open("credentials.txt",'r').read().split()
kite = KiteConnect(api_key=key_secret[0])
kite.set_access_token(access_token)


# Fetch quote details
#quote = kite.quote("INFY")

# Fetch last trading price of an instrument
#ltp = kite.ltp("NSE:INFY")

# Fetch order details
orders = kite.orders()

# Fetch position details
positions = kite.positions()

# Fetch holding details
holdings = kite.holdings()
data = pd.DataFrame(holdings)
hold = data[['tradingsymbol','average_price','last_price','close_price']]
df =hold['close_price']
x = df*0.91
exit_price=pd.DataFrame(x)
exit_price.rename(columns = {'close_price':'exit_price'}, inplace=True)
hold =hold.join(exit_price)
hold.to_csv('holdings.csv')
hold['date'] = pd.date_range(start='23/11/2020', periods=len(hold), freq='B')

hold['exit_signal'] = hold['close_price'] < hold['exit_price'] #generate exit signal

def placeMarketOrder(symbol,buy_sell,quantity):    
# Place an intraday market order on NSE
if buy_sell == "buy":
    t_type=kite.TRANSACTION_TYPE_BUY
elif buy_sell == "sell":
    t_type=kite.TRANSACTION_TYPE_SELL
kite.place_order(tradingsymbol=symbol,
                exchange=kite.EXCHANGE_NSE,
                transaction_type=t_type,
                quantity=quantity,
                order_type=kite.ORDER_TYPE_MARKET,
                product=kite.PRODUCT_MIS,
                variety=kite.VARIETY_REGULAR)

This is the hold Dataframe obtained:

Hold DF

Now based on this dataframe if the exit signal is true I want to sell that partiular stock:

The code for that is as described:

 if (hold.loc[hold['exit_signal'] == True]):
   #write code to sell stock

Now when evaluating the if statement as described above I am getting an error:

    ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

The stock can be sold in the following manner as per the def placeMarketOrder(symbol,buy_sell,quantity): :

placeMarketOrder("HDFC","buy",1,30,2200)

Hence the "HDFC" symbol will be replaced by the tradingsymbol for which exit condition is true.

How do i complete my if statement without getting the error?

1 Answers
if (hold.loc[hold['exit_signal'] == True]):

The above raises an error because hold.loc[hold['exit_signal']==True] is still a dataframe. You need to specify which entry specifically of your dataframe you are evaluating. For example,

if hold.loc[i, 'exit_signal']:
    symbol, date = hold.loc[i, 'tradingsymbol'], hold.loc[i, 'date']
    placeMarketOrder(symbol, date.month, date.day, date.year)

Now you can replace i with an index (i.e. row number) and iterate through the entire dataframe. Take a look at the different ways to loop over a dataframe - which are all more efficient than looping with plain loc indexing:

Keep in mind that it's best to avoid looping through a dataframe when possible (and it often is) as the equivalent vectorized operations (if exists and properly configured) is often orders of magnitude faster.

That said, in cases where looping is unavoidable and performance is important, you might want to take a look at:

Related