Logic for real-time Algo trading expert - python

I have made a trading expert that goes through candlesticks to check if a signal has been found then execute buy , sell orders
for i in range (len(df['Open'])) :
if some logic :
buy or sell
Now I want this expert to work on real-time data, not a historical one and I struggle with making the logic on how it'd work
what I want to do is:
Looking for the last 30 bars then make some calculations on them, then
go in a loop to check the last 2 candlesticks to see if some signal
has been found
..I want the loop to work every 4 hours since I'm working on 4h
timeframe, so with every new candlestick
I'm trying to use MetaTrader5 library
copy_rates_from_pos(
symbol, // symbol name
timeframe, // timeframe
start_pos, // initial bar index
count // number of bars
)
this code would help me find the last 30 bars but still can't get my head around on how to make the for loop !

you could use something like this
import pytz
import pandas as pd
import MetaTrader5 as mt5
import time
from datetime import datetime
from threading import Timer
server_name = "AMPGlobalUSA-Demo"
server_num = # your server num
password = # password
#------------------------------------------------------------------------------
def actualtime():
# datetime object containing current date and time
now = datetime.now()
dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
#print("date and time =", dt_string)
return str(dt_string)
#------------------------------------------------------------------------------
def sync_60sec(op):
info_time_new = datetime.strptime(str(actualtime()), '%d/%m/%Y %H:%M:%S')
waiting_time = 60 - info_time_new.second
t = Timer(waiting_time, op)
t.start()
print(actualtime(), f'waiting till next minute and 00 sec...')
#------------------------------------------------------------------------------
def program(symbol):
if not mt5.initialize(login=server_num, server=server_name, password=password):
print("initialize() failed, error code =",mt5.last_error())
quit()
timezone = pytz.timezone("Etc/UTC")
utc_from = datetime.now()
######### Change here the timeframe
rates = mt5.copy_rates_from(symbol, mt5.TIMEFRAME_M1, utc_from, 70)
mt5.shutdown()
rates_frame = pd.DataFrame(rates)
rates_frame['time']=pd.to_datetime(rates_frame['time'], unit='s')
# If you want to work only with open, high, low, close you could use
#rates_frame = rates_frame.drop(['tick_volume', 'real_volume'], axis=1)
print(f"\n", actualtime(),f"|| waiting for signals {symbol} ||\n")
if not mt5.initialize():
print("initialize() failed, error code =",mt5.last_error())
quit()
point = mt5.symbol_info(symbol).point
price = mt5.symbol_info_tick(symbol).ask
request = {
"action": mt5.TRADE_ACTION_PENDING,
"symbol": symbol,
"volume": 1.0,
"type": mt5.ORDER_TYPE_BUY_LIMIT,
"price": price,
"sl": price + 40 * point,
"tp": price - 80 * point,
"deviation": 20,
"magic": 234000,
"comment": "st_1_min_mod_3",
"type_time": mt5.ORDER_TIME_GTC,
"type_filling": mt5.ORDER_FILLING_RETURN,
}
condition_buy_1 = (
(rates_frame.close.iloc[-2] > rates_frame.open.iloc[-2])&
(rates_frame.close.iloc[-2] > rates_frame.close.iloc[-3])
)
if condition_buy_1:
#result = mt5.order_send(request)
print('Sending Order!')
# Im using AMPGlobalUSA-Demo Server
# starting mt5
if not mt5.initialize(login=server_num, server=server_name, password=password):
print("initialize() failed, error code =",mt5.last_error())
quit()
#------------------------------------------------------------------------------
# S T A R T I N G M T 5
#------------------------------------------------------------------------------
authorized=mt5.login(server_num, password=password)
if authorized:
account_info=mt5.account_info()
if account_info!=None:
account_info_dict = mt5.account_info()._asdict()
df=pd.DataFrame(list(account_info_dict.items()),columns=['property','value'])
print("account_info() as dataframe:")
print(df)
else:
print(f"failed to connect to trade account {server_num} with password={password}, error code =",mt5.last_error())
mt5.shutdown()
#------------------------------------------------------------------------------
def trading_bot():
symbol_1 = 'EURUSD'
symbol_2 = 'EURCAD'
while True:
program(symbol_1)
program(symbol_2)
time.sleep(59.8) # it depends on your computer and ping
sync_60sec(trading_bot)
Here you have the basics how to connect and operate with Python and MT5. You can save it as py file. And you have the first script looking for signals in 1 min chart for your symbol. You could have two different scripts mor looking for signals in 5 and 15 min charts, (program_5min.py and program_15min.py). You should then, add a new sync function. For example, for 5 minutes you have to wait for one hour and 0,5,10,15 minutes and so one.
Hope it works for you, have fun!

Related

How do I specify a start date using time at a particular time of the day with yfinance

Please am trying to get the stock date at a specify time of the date adding the time of which i want the stock data to be gotten from as well to so far i did something like this but i keep getting error saying data - F: Data doesn't exist for startDate = 1666286770, endDate = 1666287074
this is my code below
def watchlist():
timezone = pytz.timezone('US/Eastern')
print(type(timezone))
aware = dt.datetime.now(timezone).time()
print(aware)
global pastTime
pastTime = dt.datetime.now(timezone) - dt.timedelta(minutes=5) # time of 5minutes ago
print(pastTime)
for x in ticks:
toStr = str(x)
syb = yf.Ticker(toStr)
data = pd.DataFrame(syb.history(interval="1m",period='1d',))
data2 = pd.DataFrame(syb.history(interval="1m",period='1d',start=pastTime))
if data['Open'].sum() < data2['Open'].sum():
print(data['Open'].sum())
print(data2['Open'].sum())
print('Watch stock')
else:
print(toStr, 'Proceed to sell with robinhood')
watchlist()
Screen shot of issue

How to break down script into smaller function and create main.py? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I wrote the script in python that works perfectly fine if executed as-is. What I am trying to do is to break this script into meaningful functions and create main.py to execute this as a proper python application.
Here is my LiveStream.py code with which I am collecting data from the sensor at the beginning of every minute, and sending it to the MySQL database, and also posting it to the URL. As mentioned this works perfectly fine if I execute: python3 LiveStream.py
# Import Dependencies
import board
import pandas as pd
from busio import I2C
import adafruit_bme680
from datetime import datetime, timedelta
import time
import requests
import mysql.connector
import json
import sqlalchemy
# read database config file
with open("config.json") as config:
param = json.load(config)
# Create library object using Bus I2C port
i2c = I2C(board.SCL, board.SDA)
bme680 = adafruit_bme680.Adafruit_BME680_I2C(i2c, debug=False)
# change this to match the location's pressure (hPa) at sea level
bme680.sea_level_pressure = 1013.25
# Read data from sensors
while True:
# Create the now variable to capture the current moment
TimeStamp = datetime.now()
Temperature = round((bme680.temperature * 9/5) + 32, 2)
Gas = round(bme680.gas, 2)
Humidity = round(bme680.humidity, 2)
Pressure = round(bme680.pressure, 2)
Altitude = round(bme680.altitude, 2)
now = datetime.strftime(TimeStamp,"%Y-%m-%dT%H:%M:%S")
# Adding collected measurements into dataframe
data = pd.DataFrame([
{
"TimeStamp": now,
"Temperature": Temperature,
"Gas": Gas,
"Humidity": Humidity,
"Pressure": Pressure,
"Altitude": Altitude
}
])
# Try establishing connection with database
try:
engine = sqlalchemy.create_engine('mysql+mysqlconnector://{0}:{1}#{2}/{3}'.
format(param['MyDemoServer'][0]['user'],
param['MyDemoServer'][0]['password'],
param['MyDemoServer'][0]['host'],
param['MyDemoServer'][0]['database']), echo=False)
# Cleaning the data from existing tables MetricValues and Metrics
db_con = engine.connect()
if db_con.connect():
try:
data.to_sql('sensordata', con = db_con, if_exists = 'append', index = False)
db_con.close()
# Dispose the engine
engine.dispose()
except OSError as e:
print(e)
except OSError as e:
print(e)
# Power BI API
# BI Address to push the data to
url = 'https://api.powerbi.com/beta/94cd2fa9-eb6a-490b-af36-53bf7f5ef485/datasets/2a7a2529-dbfd-4c32-9513-7d5857b61137/rows?noSignUpCheck=1&key=nS3bP1Mo4qN9%2Fp6XJcTBgHBUV%2FcOZb0edYrK%2BtVWDg6iWwzRtY16HWUGSqB9YsqF3GHMNO2fe3r5ltB7NhVIvw%3D%3D'
# post/push data to the streaming API
headers = {
"Content-Type": "application/json"
}
response = requests.request(
method="POST",
url=url,
headers=headers,
data=json.dumps(data.to_json())
)
data = pd.DataFrame()
# Re-run the script at the beginning of every new minute.
dt = datetime.now() + timedelta(minutes=1)
dt = dt.replace(second=1)
while datetime.now() < dt:
time.sleep(1)
Here is what I have tried so far... I created a lib folder where I have etl.py file. in this file I tried creating functions such us:
def sensorsreading():
# Create library object using Bus I2C port
i2c = I2C(board.SCL, board.SDA)
bme680 = adafruit_bme680.Adafruit_BME680_I2C(i2c, debug=False)
# change this to match the location's pressure (hPa) at sea level
bme680.sea_level_pressure = 1013.25
# Read data from sensors
while True:
# Create the now variable to capture the current moment
TimeStamp = datetime.now()
Temperature = round((bme680.temperature * 9 / 5) + 32, 2)
Gas = round(bme680.gas, 2)
Humidity = round(bme680.humidity, 2)
Pressure = round(bme680.pressure, 2)
Altitude = round(bme680.altitude, 2)
now = datetime.strftime(TimeStamp, "%Y-%m-%dT%H:%M:%S")
# Adding collected measurements into dataframe
data = pd.DataFrame([
{
"TimeStamp": now,
"Temperature": Temperature,
"Gas": Gas,
"Humidity": Humidity,
"Pressure": Pressure,
"Altitude": Altitude
}
])
return data
And also function:
def dataload(data):
# Try establishing connection with database
try:
engine = sqlalchemy.create_engine('mysql+mysqlconnector://{0}:{1}#{2}/{3}'.
format(param['MyDemoServer'][0]['user'],
param['MyDemoServer'][0]['password'],
param['MyDemoServer'][0]['host'],
param['MyDemoServer'][0]['database']), echo=False)
# Cleaning the data from existing tables MetricValues and Metrics
db_con = engine.connect()
if db_con.connect():
try:
data.to_sql('sensordata', con=db_con, if_exists='append', index=False)
db_con.close()
# Dispose the engine
engine.dispose()
except OSError as e:
print(e)
except OSError as e:
print(e)
And my main.py looks like this:
import pandas as pd
from datetime import datetime, timedelta
import time
from lib.etl import *
def etl(name):
data = sensorsreading()
dataload(data)
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
etl('PyCharm')
# Re-run the script at the beginning of every new minute.
dt = datetime.now() + timedelta(minutes=1)
dt = dt.replace(second=1)
while datetime.now() < dt:
time.sleep(1)
When I run main.py it seems that I am not passing the data frame from sensorsreading() to dataload() function.
Any idea what am I doing wrong here?
To address you original question, you were using yield instead of return. Yields is used in generators, as you can read more here: https://www.geeksforgeeks.org/use-yield-keyword-instead-return-keyword-python/
In the case you don't need a precise execution, this will call the function each 60 seconds. Anyways, I'll sugest using a scheduler like systemctl or cron.
import time
while True:
etl('PyCharm')
time.sleep(60)
If you want something more precise you could use:
import time
starttime = time.time()
while True:
etl('PyCharm')
time.sleep(60.0 - ((time.time() - starttime) % 60.0))
as explained in What is the best way to repeatedly execute a function every x seconds?

Python: fetching live chat but too slow

I had to fetch live chat on Youtube and chose to use pytchat instead of Youtube API. There's no problem to fetch the chat, but it was a bit slow.
from pytchat import LiveChat
from datetime import datetime
chat = LiveChat(video_id = "36YnV9STBqc")
k=[]
while chat.is_alive():
now2 = datetime.now()
current_time2 = now2.strftime("%H:%M:%S")
print("Current Time =", current_time2,"==========") #A
try:
data = chat.get()
now3 = datetime.now()
current_time3 = now3.strftime("%H:%M:%S")
print("Current Time =", current_time3,"~~~~~~~~~~~~~") #B
for c in data.items:
comment=f"[{c.datetime}-{c.message}]"
k.append(comment) #I need to use k later
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
print(comment,"Current Time =", current_time,"++++++++++++++++")
data.tick()
except KeyboardInterrupt:
chat.terminate()
break
Below shows the output of a video with 17,649 watching: (B to A took 5 secs)
Current Time = 18:49:33 ========== #A
Current Time = 18:49:33 ~~~~~~~~~~~~~ #B
[2020-05-30 18:49:29-hi] Current Time = 18:49:33 ++++++++++++++++ #4 seconds late
[2020-05-30 18:49:32-how are you] Current Time = 18:49:36 ++++++++++++++++
Current Time = 18:49:38 ========== #A
Current Time = 18:49:38 ~~~~~~~~~~~~~ #B
[2020-05-30 18:49:32-so good] Current Time = 18:49:38 ++++++++++++++++ #6 seconds late
Below shows the output of a video with 702 watching: (B to A took at least 10 secs)
Current Time = 18:49:09 ========== #A
Current Time = 18:49:10 ~~~~~~~~~~~~~ #B
[2020-05-30 18:49:06-hellp] Current Time = 18:49:10 ++++++++++++++++
[2020-05-30 18:49:07-love the music] Current Time = 18:49:15 ++++++++++++++++
Current Time = 18:49:20 ========== #A
Current Time = 18:49:20 ~~~~~~~~~~~~~ #B
[2020-05-30 18:49:15-???] Current Time = 18:49:20 ++++++++++++++++
I assume that different watching amounts will effect the time? It's also 4 to 6 secs late to fetch every chat, is it possible to solve it? Or it's just how Pytchat works?
This is a specification.
Pytchat gets the chat in exactly the same way as the browser.
If your browser displays the time of the chat and the current time down to the second, you'll get the same results.
The response of the YouTube server is presumably affected by the number of people watching the chat and the number of people posting the chat at any given time.
It needs to be verified, but as you pointed out, I'm guessing that if a lot of chat posts are made, it's taking longer for the YouTube server to process them and return the chats that are retrieved.
(If you comment out the data.tick(), you might get a little better results.)
Use
while chat.is_alive():
data = chat.get()
for c in data.sync_items():
#c can then be formatted for ur stuff
print("Formatting stuff")
sync_items() will give you appropriate realtime chat movement.

Function with a Cooldown

Hello i have a Person Detector script i want to send an info if any person detected by mail.In order to prevent mail spamming i need a timer for sendMail function.Function might be triggered anytime but it will only respond if its not on cooldown.
I tried using async task but couldn't implemented because if a person detected it goes to a loop where it sends email every 5 minutes even if there isn’t any person detected after the first sight.
Example:
Person detection script is running.
Person detected on camera -> Send an email(start the 5 minute cooldown)
Person sighted again after 2 minutes(didn't send any email because there is still 3 minutes cooldown).
Person sighted after 6 minutes send another email(because 5 minute cooldown is over).
Summary of my code.(Necessary parts only detection and sending mail works cooldown (timer) doesn't work
async def sendAlert():
server.sendmail(sender_email, receiver_email, message)
print('sent!')
await asyncio.sleep(300)
if __name__ == "__main__":
while True:
for i in range(len(boxes)):
if classes[i] == 1 and scores[i] > threshold:
with smtplib.SMTP_SSL("smtp.gmail.com", port, context=context) as server:
sendAlert(server)
box = boxes[i]
cv2.rectangle(img,(box[1],box[0]),(box[3],box[2]),(255,0,0),2)
If there is a person detected, script will send an alert by email.Afterwards if a person detected again in 5 minutes sendAlert function shouldn't respond until 5 minutes passed
I agree with #Prune that you need to create a small (minimal) use-case and present your code so that it is not only relevant to you, but also relevant to others. Additionally, your question should have a section with a verifiable example. Without these attributes, your question becomes hard for people to grasp, solve and/or suggest any verifiable solution.
However, as I understand, you have some action (sending email if a person is detected) that you would like to perform after certain cool-off period. So, in other words, you want a mechanism of keeping track of time. Hence, you would need the datetime library.
So, your pseudo code should look something like this:
Pseudo Code
import datetime
start = capture_timestamp()
cutoff = '00:05:00'
dt_cutoff = read_in_cutoff_as_timedelta(cutoff)
if person_detected:
now = capture_timestamp()
dt = now - start
if dt >= dt_cutoff:
# Send notification
send_email_notification()
else:
# Do not Send Notification
print('now: {} | dt: {}'.format(now, dt))
You could use datetime.datetime.utcnow() for timestamp. And datetime.timedelta() for defining dt_cutoff. For reading in a time-string as time you could do this:
tm = datetime.datetime.strptime(cutoff).time()
dt_cutoff = datetime.timedelta(hours = tm.hour, minutes = tm.minute, seconds = tm.second)
I hope this gives you some idea about how to model this.
Additional Resources
https://www.guru99.com/date-time-and-datetime-classes-in-python.html
https://docs.python.org/3/library/datetime.html
https://thispointer.com/python-how-to-convert-a-timestamp-string-to-a-datetime-object-using-datetime-strptime/
Complete Solution
Now, finally if you are in a hurry to use a ready made solution, you may use the following class object as shown. All you would need is to instantiate the class object by specifying your cool-off-period (timer_cutoff) and then call the method is_timeout(). If this returns True, then you send your notification. There is also an obj.istimeout attribute which stores this decision (True/False).
import time
# Set cutoff time to 2 seconds to test the output
# after 5 seconds: expect istimeout = True
# and instantiate the TimeTracker class object.
ttk = TimeTracker(timer_cutoff = '00:00:02') # 'HH:MM:SS'
# Wait for 3 seconds
time.sleep(3)
print('start timestamp: {}'.format(ttk.timestamp_start_str))
print('cutoff timestamp'.format(ttk.timestamp_cutoff_str))
print('timer_cutoff: {}'.format(ttk.timer_cutoff_str))
# Now check if cutoff time reached
ttk.is_timeout()
print('Send Notification: {}'.format(ttk.istimeout))
print('now_timestamp: {}'.format(ttk.timestamp_now_str))
class TimeTracker
Here is the class TimeTracker class:
import datetime
class TimeTracker(object):
def __init__(self,
timer_cutoff = '00:05:00',
cutoff_strformat = '%H:%M:%S'):
self.timer_cutoff_str = timer_cutoff
self.cutoff_strformat = cutoff_strformat
self.timestamp_start, self.timestamp_start_str = self.get_timestamp()
self.dt_cutoff = None # timedelta for cutoff
self.timestamp_cutoff = None
self.timestamp_cutoff_str = None
self.update_timestamp_cutoff()
self.timestamp_now = None
self.timestamp_now_str = None
self.dt_elapsed = None
self.istimeout = False
def get_timestamp(self):
ts = datetime.datetime.utcnow()
tss = str(ts)
return (ts, tss)
def readin_cutoff_as_timedelta(self):
td = datetime.datetime.strptime(self.timer_cutoff_str,
self.cutoff_strformat)
tdm = td.time()
self.dt_cutoff = datetime.timedelta(hours = tdm.hour,
minutes = tdm.minute,
seconds = tdm.second)
def update_timestamp_cutoff(self):
self.readin_cutoff_as_timedelta()
self.timestamp_cutoff = self.timestamp_start + self.dt_cutoff
self.timestamp_cutoff_str = str(self.timestamp_cutoff)
def time_elapsed(self):
self.dt_elapsed = self.timestamp_now - self.timestamp_start
def is_timeout(self):
self.timestamp_now, self.timestamp_now_str = self.get_timestamp()
self.time_elapsed()
if (self.dt_elapsed < self.dt_cutoff):
self.istimeout = False
else:
self.istimeout = True
return self.istimeout

Given start & stop time, check if service should be on

I need to figure out if a service should be stopped or started given a start and stop time
e.g.
start_time = '16:00'
stop_time = '7:50'
if the time now is 16:50 the service should be running, if time now is 14:00, service should be stopped
start_time = '7:00'
stop_time = '20:00'
if the time now is 7:05 the service should be running, if the time is 21:00, the service should be stopped... you get the idea
so far I have this, but can't figure out the logic ;
import datetime
def test_time(start_time, stop_time):
now = datetime.datetime.now()
current_hour = int(now.hour)
current_minute = int(now.minute)
start_hour, start_minute = start_time.split(':')
stop_hour, stop_minute = stop_time.split(':')
print(f"hour: {current_hour}, minute: {current_minute}")
Use datetime to convert your text times to times. This gives you an interval during which the service should be on. If that period wraps around midnight, then split it into two intervals.
Then, simply check to see whether the current time is within the on period or off period; also check the status of the service. If the two don't match, then start/stop the service.
def sync_service(start_time, stop_time):
# start_time and stop_time are "datetime" items.
service_on = # Check status of service; return boolean
now = datetime.datetime.now()
# If interval wraps around midnight, then switch times
# to check when service is *off*
wrap_interval = stop_time < start_time
if wrap_interval:
start_time, stop_time = stop_time, start_time
# Should the service be on now?
# Check whether we're within the daily interval,
# and what type of interval we have (on or off)
want_service_on = wrap_interval != (start_time < now < stop_time)
# Adjust service status, if necessary
if want_service_on and not service_on:
service.start()
if not want_service_on and service_on:
service.stop()
Does that get you going?

Categories

Resources