Get account summary details from interactive brokers using python - python

I have some questions based on automated trading via IB using python.
I can access to TWS, but when I am request for account summary I can't put them into constant variables to use it, I only received them as an printing output.
Here my code:
from ib.ext.Contract import Contract
from ib.ext.Order import Order
from ib.opt import Connection, message
def error_handler(msg):
"""Handles the capturing of error messages"""
print "Server Error: %s" % msg
def reply_handler(msg):
"""Handles of server replies"""
print "Server Response: %s, %s" % (msg.typeName, msg)
if __name__ == "__main__":
tws_conn = Connection.create(port=4096, clientId=150)
tws_conn.connect()
tws_conn.registerAll(reply_handler)
tws_conn.reqAccountSummary(119, "All", "TotalCashValue")
time.sleep(4)
The output on the screen(cmd):
Server Response: accountSummary, <accountSummary reqId=119,
account=DU860294, tag=TotalCashValue, value=980232.77, currency=USD>
Server Response: accountSummary, <accountSummary reqId=119,
account=DUC00074, tag=TotalCashValue, value=610528.18, currency=USD>
Server Response: accountSummaryEnd, <accountSummaryEnd reqId=119>
My needed is to put all these informations into variables to use it in my program.
Thanks in advance.

You can obtain this information via updateAccountValue event too. Subscribe for this event using tws_conn.reqAccountUpdates() and you'll receive account related informations in
updateAccountValue(string key, string value, string currency, string accountName)
Then you can filter the messages like key=="TotalCashValue" and convert the value string into a double variable.

Related

Sending payload to IoT Hub for using in Azure Digital Twin using an Azure Function

Apologies for any incorrect formatting, long time since I posted anything on stack overflow.
I'm looking to send a json payload of data to Azure IoT Hub which I am then going to process using an Azure Function App to display real-time telemetry data in Azure Digital Twin.
I'm able to post the payload to IoT Hub and view it using the explorer fine, however my function is unable to take this and display this telemetry data in Azure Digital Twin. From Googling I've found that the json file needs to be utf-8 encrypted and set to application/json, which I think might be the problem with my current attempt at fixing this.
I've included a snipped of the log stream from my azure function app below, as shown the "body" part of the message is scrambled which is why I think it may be an issue in how the payload is encoded:
"iothub-message-source":"Telemetry"},"body":"eyJwb3dlciI6ICIxLjciLCAid2luZF9zcGVlZCI6ICIxLjciLCAid2luZF9kaXJlY3Rpb24iOiAiMS43In0="}
2023-01-27T13:39:05Z [Error] Error in ingest function: Cannot access child value on Newtonsoft.Json.Linq.JValue.
My current test code is below for sending payloads to IoT Hub, with the potential issue being that I'm not encoding the payload properly.
import datetime, requests
import json
deviceID = "JanTestDT"
IoTHubName = "IoTJanTest"
iotHubAPIVer = "2018-04-01"
iotHubRestURI = "https://" + IoTHubName + ".azure-devices.net/devices/" + deviceID + "/messages/events?api-version=" + iotHubAPIVer
SASToken = 'SharedAccessSignature'
Headers = {}
Headers['Authorization'] = SASToken
Headers['Content-Type'] = "application/json"
Headers['charset'] = "utf-8"
datetime = datetime.datetime.now()
payload = {
'power': "1.7",
'wind_speed': "1.7",
'wind_direction': "1.7"
}
payload2 = json.dumps(payload, ensure_ascii = False).encode("utf8")
resp = requests.post(iotHubRestURI, data=payload2, headers=Headers)
I've attempted to encode the payload correctly in several different ways including utf-8 within request.post, however this produces an error that a dict cannot be encoded or still has the body encrypted within the Function App log stream unable to decipher it.
Thanks for any help and/or guidance that can be provided on this - happy to elaborate further on anything that is not clear.
is there any particular reason why you want to use Azure IoT Hub Rest API end point instead of using Python SDK? Also, even though you see the values in JSON format when viewed through Azure IoT Explorer, the message format when viewed through a storage end point such as blob reveals a different format as you pointed.
I haven't tested the Python code with REST API, but I have a Python SDK that worked for me. Please refer the code sample below
import os
import random
import time
from datetime import date, datetime
from json import dumps
from azure.iot.device import IoTHubDeviceClient, Message
def json_serial(obj):
"""JSON serializer for objects not serializable by default json code"""
if isinstance(obj, (datetime, date)):
return obj.isoformat()
raise TypeError("Type %s not serializable" % type(obj))
CONNECTION_STRING = "<AzureIoTHubDevicePrimaryConnectionString>"
TEMPERATURE = 45.0
HUMIDITY = 60
MSG_TXT = '{{"temperature": {temperature},"humidity": {humidity}, "timesent": {timesent}}}'
def run_telemetry_sample(client):
print("IoT Hub device sending periodic messages")
client.connect()
while True:
temperature = TEMPERATURE + (random.random() * 15)
humidity = HUMIDITY + (random.random() * 20)
x = datetime.now().isoformat()
timesent = dumps(datetime.now(), default=json_serial)
msg_txt_formatted = MSG_TXT.format(
temperature=temperature, humidity=humidity, timesent=timesent)
message = Message(msg_txt_formatted, content_encoding="utf-8", content_type="application/json")
print("Sending message: {}".format(message))
client.send_message(message)
print("Message successfully sent")
time.sleep(10)
def main():
print("IoT Hub Quickstart #1 - Simulated device")
print("Press Ctrl-C to exit")
client = IoTHubDeviceClient.create_from_connection_string(CONNECTION_STRING)
try:
run_telemetry_sample(client)
except KeyboardInterrupt:
print("IoTHubClient sample stopped by user")
finally:
print("Shutting down IoTHubClient")
client.shutdown()
if __name__ == '__main__':
main()
You can edit the MSG_TXT variable in the code to match the payload format and pass the values. Note that the SDK uses Message class from Azure IoT Device library which has an overload for content type and content encoding. Here is how I have passed the overloads in the code message = Message(msg_txt_formatted, content_encoding="utf-8", content_type="application/json")
I have validated the message by routing to a Blob Storage container and could see the telemetry data in the JSON format. Please refer below image screenshot referring the data captured at end point.
Hope this helps!

NoJMSMessageIdException: MISSING_JMS_MESSAGE_ID

I'm using Python to send a STOMP message to a queue on ActiveMQ Artemis. However, when my Spring JMS application receives the message I get:
NoJMSMessageIdException: MISSING_JMS_MESSAGE_ID.
I tried to set like a header or property different values like JMSMessageID, msgID, MESSAGE_ID, etc.
I found out that my application validates the message using this method. I tried to send it with prefix id, but it didn't help. What does it expect? How to send it by stomp in Python?
The documentation of Python STOMP client has such example but it doesn't explain how to send this JMS id:
Protocol12.send(destination, body, content_type=None, headers=None,
**keyword_headers)
Send a message to a destination in the messaging system (as per
https://stomp.github.io/stomp-specification-1.2.html#SEND)
Parameters:
destination (str) – the destination (such as a message
queue - for example ‘/queue/test’ - or a message topic)
body: the content of the message
content_type (str): the MIME type of message
headers (dict): additional headers to send in the message frame
keyword_headers: any additional headers the broker requires
My code:
import stomp
import json
jsonRequest = {
"data": {
"key": "value"
}}
class MyListener(stomp.ConnectionListener):
def on_error(self, frame):
print('received an error "%s"' % frame.body)
def on_message(self, frame):
print('received a message "%s"' % frame.body)
conn = stomp.Connection([('host', 63001)])
conn.set_listener('', MyListener())
conn.connect('user', 'password', wait=True)
conn.subscribe(destination='queue', id=1, ack='auto')
conn.send(destination='queue', body=json.dumps(jsonRequest), MESSAGE_ID='e5bf8c3d-0dc4-11ed-a28a-544d36153f8c', JMSMessageID='ID:e5bf8c3d-0dc4-11ed-a28a-544d36153f5c', headers={'MESSAGE_ID': 'ID:e5bf8c3d-0dc4-11ed-a28a-544d36153f5c', 'JMSCorrelationID': '123278256677', 'JMSReplyTo': 'queue'},
MSGUID="3e4fb627-85df-4b37-b37b-1070c7893c99", TotalNumberMsg=1, CurrentNumberMsg=1, UIPSYSTEMDATA=72)
test = MyListener()
And I have error in log of back-end service:
2022-07-27 20:10:53 [,] [DefaultMessageListenerContainer-2] ERROR service.jms.listener.base.AbstractArtemisMessageListener - Exception while processing message MISSING_JMS_MESSAGE_ID
service.exception.NoJMSMessageIdException: MISSING_JMS_MESSAGE_ID
When I send message by JMS ToolBox it has this id:
2022-07-27 18:58:03 [,] [DefaultMessageListenerContainer-2] INFO service.jms.listener.base.AbstractArtemisMessageListener - Message from srv: ActiveMQMessage[ID:e5bf8c3d-0dc4-11ed-a28a-544d36153f0c]:PERSISTENT/ClientLargeMessageImpl[messageID=318412845, durable=true, address=queue,userID=e5bf8c3d-0dc4-11ed-a28a-544d36153f0c,properties=TypedProperties[__AMQ_CID=JMSToolBox-1657948224556,TotalNumberMsg=1,JMSReplyTo=queue://,_AMQ_ROUTING_TYPE=1,MSGUID=3e4fb627-85df-4b37-b37b-1070c7893c82,SERVICENAME=service,JMSCorrelationID=5515D5431364567,_AMQ_VALIDATED_USER=ACTIVEMQ.CLUSTER.ADMIN.USER,CurrentNumberMsg=1,UIPSYSTEMDATA=063224508,_AMQ_LARGE_SIZE=308737]] with correlationId: 5515D5431364567
Through the STOMP it has NULL value:
2022-07-27 19:12:52 [,] [DefaultMessageListenerContainer-2] INFO service.jms.listener.base.AbstractArtemisMessageListener - Message from srv: ActiveMQMessage[null]:NON-PERSISTENT/ClientLargeMessageImpl[messageID=318581407, durable=false, address=queue,userID=null,properties=TypedProperties[content-length=110919,destination=queue,JMSReplyTo=queue,TotalNumberMsg=1,_AMQ_ROUTING_TYPE=1,MSGUID=3e4fb627-85df-4b37-b37b-1070c7893c99,SERVICENAME=service,JMSCorrelationID=123278256677,_AMQ_VALIDATED_USER=ACTIVEMQ.CLUSTER.ADMIN.USER,CurrentNumberMsg=1,UIPSYSTEMDATA=72,_AMQ_LARGE_SIZE=110919,messageID=125774553292,JMSType=NULL-value]] with correlationId: 123278256677
Section 3.4.3 of the JMS 2 specification states (emphasis mine):
The JMSMessageID header field contains a value that uniquely identifies
each message sent by a provider.
When a message is sent, JMSMessageID is ignored. When the send method
returns it contains a provider-assigned value.
The same basic text is in section 3.4.3 of the JMS 1.1 specification as well.
The point the specification is making here is that the JMSMessageID is assigned to the message when an application sends a message using the JMS client library supplied by "the provider" (ActiveMQ Artemis in this case). However, you are not sending your message with a JMS client library. You're sending a message with a STOMP client library. Therefore, the message has no JMSMessageID assigned to it.
Furthermore, setting the JMSMessageID is actually optional even for JMS clients. See javax.jms.MessageProducer#setDisableMessageID.
Therefore, your service.jms.listener.base.AbstractArtemisMessageListener class should not consider it an error if javax.jms.Message#getJMSMessageID returns null as this is a perfectly valid possibility.

Tweepy - Skip following accounts that are private

I have a Twitter bot which is working great. However, I have encountered an issue when it comes to following users which have a private Twitter account.
The bot will send a follow request, and then keep sending the follow request even though a request has already been sent.
Is it possible to skip following back accounts that are private?
Here's the code:
#!/usr/bin/env python3.8
#followback.py
import tweepy
import logging
from config import create_api
import time
def get_friends():
# gets a list of your followers and following
followers = api.followers_ids(screen_name)
following = api.friends_ids(screen_name)
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger()
def follow_followers(api):
logger.info("Retrieving and following followers...")
for follower in tweepy.Cursor(api.followers).items():
if not follower.following:
try:
logger.info("Now following "+ (follower.screen_name))
follower.follow()
except tweepy.TweepError as error:
if error.api_code == 160:
logger.info("Already sent a follow request to " + (follower.screen_name) + ". Attempting to skip.")
def main():
api = create_api()
while True:
follow_followers(api)
logger.info("Waiting...")
time.sleep(120)
if __name__ == "__main__":
main()
I have now added some code:
if error.api_code == 160:
logger.info("Already sent a follow request to " + (follower.screen_name) + ".
Which catches the error and looks neater in the log, but it is filling the log up with:
INFO:root:Retrieving and following followers...
INFO:root:Now following "user a"
INFO:root:Already sent a follow request to "user a". Attempting to skip.
INFO:root:Now following "user b"
INFO:root:Already sent a follow request to "user b". Attempting to skip.
INFO:root:Waiting...
INFO:root:Retrieving and following followers...
INFO:root:Now following "user a"
INFO:root:Already sent a follow request to "user a". Attempting to skip.
INFO:root:Now following "user b"
INFO:root:Already sent a follow request to "user b". Attempting to skip.
INFO:root:Waiting...
Both user a and user b in this example are private accounts.
Let me know if you require any further information, thanks.
You can check the protected attribute of each User object, e.g. if not follower.protected:.

Python to Json DeserializerError

I am trying to read values from PLC using the IOTHub telemetry and stream them to PowerBI using azure.
I was able to connect to the PLC and read the values when I run the code and am able to see the hub receive the messages. However, the stream gives me an error that says 'InputDeserializerError.InvalidData'. I am not sure where I went wrong. Please have a look at the below code and suggest how I could serialize it. When I remove the string values and only run integers & float, the stream picks it up.
# Define the JSON message to send to IoT Hub.
MSG_TXT = "{\"Bin1Load\": %s,\"Bin1Grower\": %s,\"Bin1Variety\": %s,\"Bin1StatedTn\": %.2f,\"Bin1S\": %.3f,\"Bin1CalcV\": %.2f}"
def send_confirmation_callback(message, result, user_context):
print ( "IoT Hub responded to message with status: %s" % (result) )
def iothub_client_init():
# Create an IoT Hub client
client = IoTHubClient(CONNECTION_STRING, PROTOCOL)
return client
def iothub_client_telemetry_sample_run():
try:
client = iothub_client_init()
print ( "IoT Hub device sending periodic messages, press Ctrl-C to exit" )
while True:
# Build the message with simulated telemetry values.
b1load = comm.Read('Bin01.Content.Load')
b1grower = comm.Read('Bin01.Content.Grower')
b1variety = comm.Read('Bin01.Content.Variety')
b1statedton = comm.Read('Bin01.Content.Stated_Tn')
b1s = comm.Read('Bin01.Content.SG')
b1calcvol = comm.Read('Bin01.Content.Calc_Vol')
msg_txt_formatted = MSG_TXT % (b1loads, b1growers, b1varietys, b1statedton, b1s, b1calcvol)
message = IoTHubMessage(msg_txt_formatted)```
Solution:
Don't try to build JSON with string formatting. Create a dictionary and use json.dumps().

Websocket to useable data in Python - get price from GDAX websocket feed

I am trying to get the last price data to use which is easy enough using polling on /ticker endpoint i.e.
rawticker = requests.get('https://api.gdax.com/products/BTC-EUR/ticker')
json_data = json.loads(rawticker.text)
price = json_data['price']
but the GDAX API discourages polling. How could I get the same information using websocket. How could I get the following code to run just once and then extract the price information.
from websocket import WebSocketApp
from json import dumps, loads
from pprint import pprint
URL = "wss://ws-feed.gdax.com"
def on_message(_, message):
"""Callback executed when a message comes.
Positional argument:
message -- The message itself (string)
"""
pprint(loads(message))
print
def on_open(socket):
"""Callback executed at socket opening.
Keyword argument:
socket -- The websocket itself
"""
params = {
"type": "subscribe",
"channels": [{"name": "ticker", "product_ids": ["BTC-EUR"]}]
}
socket.send(dumps(params))
def main():
"""Main function."""
ws = WebSocketApp(URL, on_open=on_open, on_message=on_message)
ws.run_forever()
if __name__ == '__main__':
main()
Thanks for any help.
Pulling is discouraged when you want to have real-time updates. In that case, it is recommended to use Web Sockets. In your case, however, running the code once and exiting, it is fine to use the pull endpoint.
To answer your question anyway. on_message's first argument is the WebSocketApp you can simply add this line to close it after receiving the first message.
def on_message(ws, message):
"""Callback executed when a message comes.
Positional argument:
message -- The message itself (string)
"""
pprint(loads(message))
ws.close()
Tip
Requests library has built-in .json() that you can use directly on the .get() return
import requests
rawticker = requests.get('https://api.gdax.com/products/BTC-EUR/ticker').json()
price = rawticker['price']
print(price)

Categories