How do I append data in google sheet using python? - python

I am trying to download the data from IB api and upload it onto a google sheet. If the data already exists in the sheet, then I want the new data to be added into the sheet without overwriting the previous data. This is what I have done so far:
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
from threading import Timer
import pandas as pd
from datetime import datetime
import os
import pygsheets
class TestApp(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.df = pd.DataFrame(columns=['accountName', 'contract', 'position','marketPrice', 'marketValue', 'averageCost', 'unrealizedPNL','realizedPNL'])
self.df1 = pd.DataFrame(columns=['key', 'value', 'currency'])
def error(self, reqId, errorCode, errorString):
print("Error: ", reqId, " ", errorCode, " ", errorString)
def nextValidId(self,orderId):
self.start()
def updatePortfolio(self, contract: Contract, position: float, marketPrice: float, marketValue: float,
averageCost: float, unrealizedPNL: float, realizedPNL: float, accountName: str):
self.df.loc[len(self.df)] = [accountName, contract.symbol,position,marketPrice, marketValue,averageCost, unrealizedPNL,realizedPNL]
# See unrealized P&L, which will be the total unrealized P&L since the position was open, the
# realized P&L which would be the realized profit loss for the current day
# If you’ve closed out any positions, as well as the account name, the current market value,
# the average cost used to open the position and of course the position size
print("UpdatePortfolio.", "Symbol:", contract.symbol, "SecType:", contract.secType, "Exchange:",
contract.exchange,
"Position:", position, "MarketPrice:", marketPrice, "MarketValue:", marketValue, "AverageCost:",
averageCost,
"UnrealizedPNL:", unrealizedPNL, "RealizedPNL:", realizedPNL, "AccountName:", accountName)
def updateAccountValue(self, key: str, val: str, currency: str, accountName: str):
# returns the cash balance, the required margin for the account, or the net liquidity
self.df1.loc[len(self.df)] = ['ExchangeRate', val, currency]
print("UpdateAccountValue. Key:", key, "Value:", val, "Currency:", currency, "AccountName:", accountName)
def updateAccountTime(self, timeStamp: str):
print("UpdateAccountTime. Time:", timeStamp)
def accountDownloadEnd(self, accountName: str):
print("AccountDownloadEnd. Account:", accountName)
def start(self):
# ReqAccountUpdates - This function causes both position and account information to be returned for a specified account
# Invoke ReqAccountUpdates with true to start a subscription
self.reqAccountUpdates(True, "U0000000") # <----- Change account number here
def stop(self):
self.reqAccountUpdates(False,"U00000") # <----- Change account number here
self.done = True
self.disconnect()
def main():
app = TestApp()
app.connect("127.0.0.1", 7496, 0)
Timer(5, app.stop).start()
app.run()
# service file is the ib_data json file key
service_file_path = "googlesheet_api_json"
gc = pygsheets.authorize(service_file= service_file_path )
spreadsheet_id = '00000'
sh = gc.open_by_key(spreadsheet_id)
# inserting date and time to the data
now = datetime.now()
dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
app.df['Date_Time'] = dt_string
#check if the google sheet has previous data
wk_sheet_stock = gc.open('workbook').sheet1
cells = wk_sheet_stock.get_all_values(include_tailing_empty_rows=False, include_tailing_empty=False, returnas='matrix')
if len(cells) < 1:
print('no data in the file')
data_write = sh.worksheet_by_title('stocks')
data_write.clear('A1',None,'*')
data_write.set_dataframe(app.df, (1,1), encoding='utf-8', fit=True)
data_write.frozen_rows = 1
data_write = sh.worksheet_by_title('currency')
data_write.clear('A1', None, '*')
data_write.set_dataframe(app.df1, (1, 1), encoding='utf-8', fit=True)
data_write.frozen_rows = 1
else:
print('adding data to the file')
stock_df_values = app.df.values.tolist()
currency_df_values = app.df1.values.tolist()
sh.values_append('stocks', {'valueInputOption': 'RAW'}, {'values': stock_df_values})
sh.values_append('currency', {'valueInputOption': 'RAW'}, {'values': currency_df_values})
if __name__ == "__main__":
main()
I get the error: AttributeError: 'Spreadsheet' object has no attribute 'values_append'
I am confused as to how do I go about this. Thank you for your help!

I believe your goal is as follows.
You want to append the values using values_append.
You want to remove your current issue of I get the error: AttributeError: 'Spreadsheet' object has no attribute 'values_append'.
You want to achieve this using pygsheets for python.
Modification points:
When I saw the document of pygsheets, it seems that the method of values_append is for class pygsheets.sheet.SheetAPIWrapper. In this case, sh of sh = gc.open_by_key(spreadsheet_id) is not it. I think that this might be the reason for your current issue of AttributeError: 'Spreadsheet' object has no attribute 'values_append'.
And, I cannot know your values of stock_df_values and currency_df_values. So, in this answer, I propose a modification point by guessing that those values are the 2-dimensional array. Please be careful about this.
When these points are reflected in your script, how about the following modification?
From:
sh.values_append('stocks', {'valueInputOption': 'RAW'}, {'values': stock_df_values})
sh.values_append('currency', {'valueInputOption': 'RAW'}, {'values': currency_df_values})
To:
gc.sheet.values_append(spreadsheet_id, stock_df_values, "ROWS", "stocks")
gc.sheet.values_append(spreadsheet_id, currency_df_values, "ROWS", "currency")
Note:
I guessed that the values of "stocks" and "currency" are the sheet names in the Spreadsheet of sh = gc.open_by_key(spreadsheet_id). Please be careful about this.
If you cannot know whether the values of stock_df_values and currency_df_values are a 2-dimensional array, please modify them as follows.
gc.sheet.values_append(spreadsheet_id, stock_df_values if isinstance(stock_df_values[0], list) else [stock_df_values], "ROWS", "stocks")
gc.sheet.values_append(spreadsheet_id, currency_df_values if isinstance(currency_df_values[0], list) else [currency_df_values], "ROWS", "currency")
In this answer, I suppose that other parts except for sh.values_append of your script work fine. Please be careful about this.
Reference:
values_append

Related

How to use weatherstack.com api

Hi I'm pretty new to python. I try to make a chatbot with rasa for personal use. Would like to add weather api now. I use weatherstack.com. If I use their example this works, but if I adjust it to my own liking I always end up with the same error.
condition = api_response['current']['weather_descriptions'] TypeError: list indices must be integers or slices, not str
This is the code I am using.
class Actionweatherapi(Action):
def name(self):
return "actions.weatherapi"
def run(self, dispatcher, tracker, domain):
import requests
location = tracker.get_slot('location')
if location == 'None':
location = 'fetch:ip'
api_result = requests.get('http://api.weatherstack.com/current?access_key=0000000&query={}'.format(location))
api_response = api_result.json()
country = api_response['request']['query']
condition = api_response['current']['weather_descriptions']
temperature_c = api_response['current']['temperature']
humidity = api_response['current']['humidity']
wind_mph = api_response['current']['wind_speed']
response = """It is currently {} in {} at the moment. The temperature is {} degrees, the humidity is {}% and the wind speed is {} mph.""".format(condition, country, temperature_c, humidity, wind_mph)
dispatcher.utter_message(response)
return [AllSlotsReset()]
I have also reviewed the printf-style String Formatting on the python website, but I cannot figure out how to get it working.
The json response is like this example
http://api.weatherstack.com/current?access_key=1c80e8b9fe4fcef4f8d6fd7514a8e9e9&query=New%20York

Hi ! need help in choice of class with a customer - appointment table

I'm trying to build a "customer" menu textbased to make automatic appointments and manage conflicts. I'm using Python but so far I've been using procedural programming (I'm a newbie), but it's getting too complicated to maintain. I would like to use a CSV file to keep all the contact (up to a thousand) and calcurse to manage my calendar.
Basically, I would like to check if the contact is approved and then send him my availabilities. I try to use the datefinder module to get a date & time, check if available, and ask for the order.
I'd like to know what class I need to create:
import csv
import datetime
import time
class Contact:
def __init__(self, index, name, last_time, last_level='unreliable', appdate=None, apporder=None, appnote=None):
self.index = index
self.name = name
self.last_time = last_time #last time I received a message from this person to unlogg if it's
over 5min agoo
self.last_level = last_level # can be unreliable,main,date,order,note as
# unreliable= don't even send availibities
# main=the person is logged send availibities
# date=ask for date, order=ask for order, note=ask for note
self.appdate = datetime.datetime.strptime(appdate, '%Y-%m-%d %H:%M').date()
self.apporder = apporder
self.appnote = appnote
class Appointment:
# I'd like to create a class for all the appointments from the calcurse file listing all the appointments to be able to check for instances if any conflicts with any new appointments.
def __init__(self, name, appdate, apporder, appnote):
self.name = name
self.appdate = datetime.datetime.strptime(appdate, '%Y-%m-%d %H:%M')
self.apporder = apporder
self.appnote = appnote
def find_contact_in_file(name):
try:
with open("contact", 'r') as csvfile:
reader = csv.reader(csvfile)
index = 0
for line in reader:
index += 1
if line[0] == name:
print(index, line)
contact = Contact(index, line[0], line[1], line[2], line[3], line[4], line[5])
return contact
return contact.Contact(index + 1, name, int(time.time()), "unreliable", None, None, None)
except IOError:
print("I/O error")
Do I need a class Reply to make the reply from the message I get from the customer?

Python multiple requests with single code

I am using the IB API to retrieve historical stock data, and I would like my code to run multiple times with different variables (different stocks and timeframes).
Currently I am using the following code:
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
def print_to_file(*args):
with open('text6.txt', 'a') as fh:
fh.write(' '.join(map(str,args)))
fh.write('\n')
print = print_to_file
class TestApp(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
Layout = "{!s:1} {!s:2} {!s:3} {!s:4} {!s:5} {!s:6} {!s:7} {!s:8} {!s:8} '\n'"
print(Layout.format("Ticker;", "Date;", "None;", "Time;", "Open;", "High;", "Low;", "Close;", "Volume"))
def historicalData(self, reqId, bar):
print("AAPL", ";", bar.date.replace(' ', '; '), ";", bar.open, ";", bar.high, ";", bar.low, ";", bar.close, ";", bar.volume)
def main():
app = TestApp()
app.connect("127.0.0.1", 7497, 0)
contract = Contract ()
contract.symbol = "AAPL"
contract.secType = "STK"
contract.exchange = "SMART"
contract.currency = "USD"
contract.primaryExchange = "NASDAQ"
app.reqHistoricalData(0, contract, "20180201 10:00:00", "1 M", "1 min", "TRADES", 0, 1, False, [])
app.run()
if __name__ == "__main__":
main()
I have tried the following for multiple stocks:
contract.symbol = ["AAPL", "GOOG"]
But this gives me the error message:
No security definition has been found for the request
And using the following code for time & date:
app.reqHistoricalData(0, contract, ["20180201 10:00:00", "20180301 10:00:00"], "1 M", "1 min", "TRADES", 0, 1, False, [])
Gives me the error message:
Error validating request:-'bP' : cause - Historical data query end date/time string [['20180201 10:00:00', '20180301 10:00:00']] is invalid. Format is 'YYYYMMDD{SPACE}hh:mm:ss[{SPACE}TMZ]'.
Basically I would like this .py file to run multiple requests in a single run, using multiple variables so that I can receive data for multiple stocks in a single run.
Could anybody here help me to achieve this?
Thanks!
You can create a class that derives from the Contract class in order to create multiple Contract objects at one time. Then, make a loop that passes your Contract objects into the client in order to get the data. What you are currently doing is pretty far off from any implementation that would actually work. Check out this blog for help with the set-up of a working system -> https://qoppac.blogspot.com/2017/03/interactive-brokers-native-python-api.html
As far as the contract class, look at the relevant parameters in the documentation and create a class as necessary. Here is an example of my futures class:
class IBFutures(Contract):
def __init__(self, symbol:str, exchange:str, secType:str,
currency = 'USD', localSymbol = ""):
Contract.__init__(self)
self.symbol = symbol
self.secType = secType
self.exchange = exchange
self.currency = currency
self.localSymbol = localSymbol
Then, in your client object, make a function similar to this:
def getHistoricalData(self, contracts, durationStr="3 D", barSizeSetting="30 mins", whatToShow = "TRADES"):
"""
Returns historical prices for a contract, up to today
ibcontract is a Contract
:returns list of prices in 4 tuples: Open high low close volume
"""
defaultid = 80
prices = {}
for symbol in contracts:
defaultid += 1 # update defaultid
# Make a place to store the data we're going to return
historic_data_queue = finishableQueue(self.init_historicprices(defaultid))
# Should endDateTime be set to 9:00AM EST??
# Request some historical data. Native method in EClient
self.reqHistoricalData(reqId=defaultid, contract = contracts[symbol],
endDateTime=datetime.datetime.today().strftime("%Y%m%d %H:%M:%S"),
durationStr=durationStr, barSizeSetting=barSizeSetting,
whatToShow=whatToShow, useRTH=0, formatDate=1,
keepUpToDate=False, chartOptions=[])
# Wait until we get a completed data, an error, or time-out
MAX_WAIT_SECONDS = 30
logger.info("Getting %s historical data from the server..." % symbol)
historic_data = historic_data_queue.get(timeout=MAX_WAIT_SECONDS)
clean_data = cleanPrice(data=historic_data)
prices[symbol] = clean_data
if historic_data_queue.timed_out():
logger.info("Exceeded maximum wait for wrapper to confirm finished")
self.cancelHistoricalData(defaultid)
logger.info("Prices retrieved for %d contracts" % len(prices))
return prices

Using Python Classes and Lists to print reports from a csv

I have a homework assignment that I have been stuck on for several days.
Basic problem description:
Incident class has properties: ID, time, type, location, narrative and status
methods: init, brief, isMorning, resolve
script takes one argument, the full path of crime report csv.
First few lines of CSV:
ID Time Type Location Narrative
1271 11:54 AM Drug Violation Wolf Ridge Report of possible drug violation. Student was referred to the university.
My code so far:
import sys
class Incident:
def __init__(self, ID, time, type, location, narrative, status):
self.ID = id
self.time = time
self.type = type
self.location = location
self.narrative = narrative
self.status = status
def brief(self):
print '''{0}: {1}, {2}
{3}
'''.format(self.ID, self.type, self.status, self.narrative)
def isMorning(self):
if 'AM' in self.time:
return True
else:
return False
def resolve(self):
if self.status == 'Pending':
self.status = 'Resolved'
try:
dataset = sys.argv[1] except IndexError:
print 'Usage: Requires full path input file name.'
sys.exit()
# Create an empty list to contain the Incident objects. crimeList = []
# Read the crime report. with open(dataset, 'r') as f:
# Read the header.
headers = f.readline().split(',')
# Read each record and parse the attributes.
for line in f:
lineList = line.strip().split(',')
reportNumber = lineList[0]
timeReported = lineList[1]
incidentType = lineList[2]
location = lineList[3]
narrative = lineList[4]
status = lineList[5].strip()
### Create initialize an Incident object instance and store it in a variable
crime = Incident(reportNumber, timeReported, incidentType, location, narrative, status)
### Append the new Incident object to the crimeList.
crimeList.append(crime)
What i'm stuck on:
I need to access the "nth" Incident in the crimeList and run various methods. I can't seem to find a way to access the item and have it functional to run methods on.
I've tried enumerating and splicing but just can't get anything to work?
Anyone have any suggestions?
Look up the nth crime from your crimeList like so: x=crimeList[n], and then call the methods on that instance: x.brief(), x.resolve(), etc.

PyYaml Expect scalar but found Sequence

I am trying to load with user defined tags in my python code, with PyYaml. Dont have much experience with pyYaml loader, constructor, representer parser, resolver and dumpers.
Below is my code what i could come up with:
import yaml, os
from collections import OrderedDict
root = os.path.curdir
def construct_position_object(loader, suffix, node):
return loader.construct_yaml_map(node)
def construct_position_sym(loader, node):
return loader.construct_yaml_str(node)
yaml.add_multi_constructor(u"!Position", construct_position_object)
yaml.add_constructor(u"!Position", construct_position_sym)
def main():
file = open('C:\calcWorkspace\\13.3.1.0\PythonTest\YamlInput\Exception_V5.yml','r')
datafile = yaml.load_all(file)
for data in datafile:
yaml.add_representer(literal, literal_presenter)
yaml.add_representer(OrderedDict, ordered_dict_presenter)
d = OrderedDict(l=literal(data))
print yaml.dump(data, default_flow_style=False)
print datafile.get('abcd').get('addresses')
yaml.add_constructor('!include', include)
def include(loader, node):
"""Include another YAML file."""
global root
old_root = root
filename = os.path.join(root, loader.construct_scalar(node))
root = os.path.split(filename)[0]
data = yaml.load(open(filename, 'r'))
root = old_root
return data
class literal(str): pass
def literal_presenter(dumper, data):
return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|')
def ordered_dict_presenter(dumper, data):
return dumper.represent_dict(data.items())
if __name__ == '__main__':
main()
This is my Yaml file:
#sid: Position[SIK,sourceDealID,UTPI]
sid: Position[1232546, 0634.10056718.0.1096840.0,]
ASSET_CLASS: "Derivative"
SOURCE_DEAL_ID: "0634.10056718.0.1096840.0"
INSTR_ID: "UKCM.L"
PRODUCT_TYPE_ID: 0
SOURCE_PRODUCT_TYPE: "CDS"
NOTIONAL_USD: 14.78
NOTIONAL_CCY:
LOB:
PRODUCT_TYPE:
#GIM
UNDERLIER_INSTRUMENT_ID:
MTM_USD:
MTM_CCY:
TRADER_SID:
SALES_PERSON_SID:
CLIENT_SPN:
CLIENT_UCN:
CLIENT_NAME:
LE:
---
sid: Position[1258642, 0634.10056718.0.1096680.0,]
#sid: Position[1]
ASSET_CLASS: "Derivative"
SOURCE_DEAL_ID: "0634.10056718.0.1096840.0"
INSTR_ID: "UKCM.L"
PRODUCT_TYPE_ID: 0
SOURCE_PRODUCT_TYPE: "CDS"
NOTIONAL_AMT: 18.78
NOTIONAL_CCY: "USD"
LOB:
PRODUCT_TYPE:
UNDERLIER_INSTRUMENT_ID:
MTM_AMT:
MTM_CCY:
TRADER_SID:
SALES_PERSON_SID:
CLIENT_SPN:
CLIENT_UCN:
CLIENT_NAME:
LE:
---
# Excption documents to follow from here!!!
Exception:
src_excp_id: 100001
# CONFIGURABLE OBJECT, VALUE TO BE POPULATED RUNTIME (impact_obj COMES FROM CONFIG FILE)
# VALUE STARTS FROM "!POSITION..." A USER DEFINED DATATYPE
impact_obj: !Position [1232546, 0634.10056718.0.1096840.0,]
# CONFIGURABLE OBJECT, VALUE TO BE POPULATED RUNTIME (rsn_obj COMES FROM CONFIG FILE)
# VALUE STARTS FROM "_POSITION..." AN IDENTIFIER FOR CONFIGURABLE OBJECTS
rsn_obj: !Position [1258642, 0634.10056718.0.1096680.0,]
exception_txt: "Invalid data, NULL value provided"
severity: "High"
Looks like my code is unable to identify the !Position user-defined data type.
Any help would be appericiated
Regards.
Needed to change:
def construct_position_sym(loader, node):
return loader.construct_yaml_str(node)
to :
def construct_position_sym(loader, node):
return loader.construct_yaml_seq(node)
Because the position object was a sequence:
!Position [something, something]
So the constructor had to be a sequence type. Works perfect!!!

Categories