# installing Metatrader5 using sys
import sys
# python MetaTrader5
#!{sys.executable} -m pip install MetaTrader5
#mt5se
!{sys.executable} -m pip install mt5se --upgrade
import mt5se as se
connected=se.connect()
if connected:
print('Ok!! It is connected to the Stock exchange!!')
else:
print('Something went wrong! It is NOT connected to se!!')
ti=se.terminal_info()
print('Metatrader program file path: ', ti.path)
print('Metatrader path to data folder: ', ti.data_path )
print('Metatrader common data path: ',ti.commondata_path)
acc=se.account_info() # it returns account's information
print('login=',acc.login) # Account id
print('balance=',acc.balance) # Account balance in the deposit currency using buy price of assets (margin_free+margin)
print('equity=',acc.equity) # Account equity in the deposit currency using current price of assets (capital liquido) (margin_free+margin+profit)
print('free margin=',acc.margin_free) # Free margin ( balance in cash ) of an account in the deposit currency(BRL)
print('margin=',acc.margin) #Account margin used in the deposit currency (equity-margin_free-profit )
print('client name=',acc.name) #Client name
print('Server =',acc.server) # Trade server name
print('Currency =',acc.currency) # Account currency, BRL for Brazilian Real
import pandas as pd
# Some example of Assets in Nasdaq
assets=[
'AAL', # American Airlines Group, Inc.
'GOOG', # Apple Inc.
'UAL', # United Airlines Holdings, Inc.
'AMD', # Advanced Micro Devices, Inc.
'MSFT' # MICROSOFT
]
asset=assets[0]
df=se.get_bars(asset,10) # it returns the last 10 days
print(df)
print('Position=',se.get_positions()) # return the current value of assets (not include balance or margin)
symbol_id='MSFT'
print('Position on paper ',symbol_id,' =',se.get_position_value(symbol_id)) # return the current position in a given asset (symbol_id)
pos=se.get_position_value(symbol_id)
print(pos)
###Buying three hundred shares of AAPL !!
symbol_id='AAPL'
bars=se.get_bars(symbol_id,2)
price=se.get_last(bars)
volume=300
b=se.buyOrder(symbol_id,volume, price ) # price, sl and tp are optional
if se.is_market_open(symbol_id):
print('Market is Open!!')
else:
print('Market is closed! Orders will not be accepted!!')
if se.checkOrder(b):
print('Buy order seems ok!')
else:
print('Error : ',se.getLastError())
# if se.sendOrder(b):
# print('Order executed!)
import mt5se as se
import pandas as pd
import time
asset='AAPL'
def run(asset):
if se.is_market_open(asset): # change 'if' for 'while' for running until the end of the market session
print("getting information")
bars=se.get_bars(asset,14)
curr_shares=se.get_shares(asset)
# number of shares that you can buy
price=se.get_last(bars)
free_shares=se.get_affor_shares(asset,price)
rsi=se.tech.rsi(bars)
print("deliberating")
if rsi>=70 and free_shares>0:
order=se.buyOrder(asset,free_shares)
elif rsi<70 and curr_shares>0:
order=se.sellOrder(asset,curr_shares)
else:
order=None
print("sending order")
# check and send (it is sent only if check is ok!)
if order!=None:
if se.checkOrder(order) and se.sendOrder(order):
print('order sent to se')
else:
print('Error : ',se.getLastError())
else:
print("No order at the moment for asset=",asset )
time.sleep(1) # waits one second
print('Trader ended operation!')
if se.connect()==False:
print('Error when trying to connect to se')
exit()
else:
run(asset) # trade asset PETR4
#Multiple asset Robot (Example), single strategy for multiple assets, where the resources are equally shared among the assets
import time
def runMultiAsset(assets):
if se.is_market_open(assets[0]): # change 'if' for 'while' for running until the end of the market session
for asset in assets:
bars=se.get_bars(asset,14) #get information
curr_shares=se.get_shares(asset)
money=se.account_info().margin_free/len(assets) # number of shares that you can buy
price=se.get_last(bars)
free_shares=se.get_affor_shares(asset,price,money)
rsi=se.tech.rsi(bars)
if rsi>=70 and free_shares>0:
order=se.buyOrder(asset,free_shares)
elif rsi<70 and curr_shares>0:
order=se.sellOrder(asset,curr_shares)
else:
order=None
if order!=None: # check and send if it is Ok
if se.checkOrder(order) and se.sendOrder(order):
print('order sent to se')
else:
print('Error : ',se.getLastError())
else:
print("No order at the moment for asset=",asset)
time.sleep(1)
print('Trader ended operation!')
assets=['GOOG','AAPL']
runMultiAsset(assets) # trade asset
import mt5se as se
from datetime import datetime
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
asset='MSFT'
se.connect()
bars=se.get_bars(asset,252) # 252 business days (basically one year)
x=se.get_returns(bars) # calculate daily returns given the bars
#With a small change we can see the historgram of weekly returns
#x=se.getReturns(bars,offset=5)
plt.hist(x,bins=16) # creates a histogram graph with 16 bins
plt.grid()
plt.show()
You may use an alternative method to build your robots, that may reduce your workload. It is called inverse control robots. You receive the most common information requrired by robots and returns your orders
Let's some examples of Robots based on Inversion of Control including the multiasset strategy presented before in a inverse control implementation
Inversion of control Traders are classes that inherint from se.Trader and they have to implement just one function: trade: It is called at each moment, with dbars. It should returns the list of orders to be executed or None if there is no order at the moment
Your trader may also implement two other function if required: setup: It is called once when the operation starts. It receives dbars ('mem' bars from each asset) . See the operation setup, for more information
ending: It is called one when the sheculed operation reaches its end time.
Your Trader class may also implement a constructor function
Let's see an Example!
import numpy.random as rand
class RandomTrader(se.Trader):
def __init__(self):
pass
def setup(self,dbars):
print('just getting started!')
def trade(self,dbars):
orders=[]
assets=ops['assets']
for asset in assets:
if rand.randint(2)==1:
order=se.buyOrder(asset,100)
else:
order=se.sellOrder(asset,100)
orders.append(order)
return orders
def ending(self,dbars):
print('Ending stuff')
if issubclass(RandomTrader,se.Trader):
print('Your trader class seems Ok!')
else:
print('Your trader class should a subclass of se.Trader')
trader=RandomTrader() # DummyTrader class also available in se.sampleTraders.DummyTrader()
class MultiAssetTrader(se.Trader):
def trade(self,dbars):
assets=dbars.keys()
orders=[]
for asset in assets:
bars=dbars[asset]
curr_shares=se.get_shares(asset)
money=se.get_balance()/len(assets) # divide o saldo em dinheiro igualmente entre os ativos
# number of shares that you can buy of asset
price=se.get_last(bars)
free_shares=se.get_affor_shares(asset,price,money)
rsi=se.tech.rsi(bars)
if rsi>=70 and free_shares>0:
order=se.buyOrder(asset,free_shares)
elif rsi<70 and curr_shares>0:
order=se.sellOrder(asset,curr_shares)
else:
order=None
if order!=None:
orders.append(order)
return orders
if issubclass(MultiAssetTrader,se.Trader):
print('Your trader class seems Ok!')
else:
print('Your trader class should a subclass of se.Trader')
trader=MultiAssetTrader()
The evaluation for trading robots is usually called backtesting. That means that a trading robot executes with historical price series , and its performance is computed
In backtesting, time is discretized according with bars and the package mt5se controls the information access to the Trader according with the simulated time.
To backtest one strategy, you just need to create a subclass of Trader and implement one function: trade
You may implement function setup, to prepare the Trader Strategy if it is required and a function ending to clean up after the backtest is done
The simulation time advances and in function 'trade' the Trader class receives the new bar info and decides wich orders to send
## Defines the Trader
class MonoAssetTrader(se.Trader):
def trade(self,dbars):
assets=dbars.keys()
asset=list(assets)[0]
orders=[]
bars=dbars[asset]
curr_shares=se.get_shares(asset)
# number of shares that you can buy
price=se.get_last(bars)
free_shares=se.get_affor_shares(asset,price)
rsi=se.tech.rsi(bars)
if rsi>=70:
order=se.buyOrder(asset,free_shares)
else:
order=se.sellOrder(asset,curr_shares)
if rsi>=70 and free_shares>0:
order=se.buyOrder(asset,free_shares)
elif rsi<70 and curr_shares>0:
order=se.sellOrder(asset,curr_shares)
if order!=None:
orders.append(order)
return orders
trader=MonoAssetTrader() # also available in se.sampleTraders.MonoAssetTrader()
print(trader)
# sets Backtest options
prestart=se.date(2018,12,10)
start=se.date(2019,1,10)
end=se.date(2019,2,27)
capital=1000000
results_file='data_equity_file.csv'
verbose=False
assets=['AAPL']
# Use True if you want debug information for your Trader
#sets the backtest setup
period=se.DAILY
# it may be se.INTRADAY (one minute interval)
bts=se.backtest.set(assets,prestart,start,end,period,capital,results_file,verbose)
# check if the backtest setup is ok!
if se.backtest.checkBTS(bts):
print('Backtest Setup is Ok!')
else:
print('Backtest Setup is NOT Ok!')
# Running the backtest
df= se.backtest.run(trader,bts)
# run calls the Trader. setup and trade (once for each bar)
#print the results
print(df)
# evaluates the backtest results
se.backtest.evaluate(df)
The method backtest.run creates a data file with the name given in the backtest setup (bts)
This will give you a report about the trader performance
We need ot note that it is hard to perform meaningful evaluations using backtest. There are many pitfalls to avoid and it may be easier to get trading robots with great performance in backtest, but that perform really badly in real operations.
More about that in mt5se backtest evaluation chapter.
For a deeper discussion, we suggest: Is it a great Autonomous Trading Strategy or you are just fooling yourself Bernardini,M. and Castro, P.A.L
In order to analyze the trader's backtest, you may use :
se.backtest.evaluateFile(fileName) #fileName is the name of file generated by the backtest or se.bactest.evaluate(df) # df is the dataframe returned by se.backtest.run
import mt5se as se
class MultiAssetTrader(se.Trader):
def trade(self,dbars):
assets=dbars.keys()
orders=[]
for asset in assets:
bars=dbars[asset]
curr_shares=se.get_shares(asset)
money=se.get_balance()/len(assets) # divide o saldo em dinheiro igualmente entre os ativos
# number of shares that you can buy of asset
price=se.get_last(bars)
free_shares=se.get_affor_shares(asset,price,money)
rsi=se.tech.rsi(bars)
if rsi>=70 and free_shares>0:
order=se.buyOrder(asset,free_shares)
elif rsi<70 and curr_shares>0:
order=se.sellOrder(asset,curr_shares)
else:
order=None
if order!=None:
orders.append(order)
return orders
trader=MultiAssetTrader() # also available in se.sampleTraders.MultiAssetTrader()
print(trader)
# sets Backtest options
prestart=se.date(2020,5,4)
start=se.date(2020,5,6)
end=se.date(2020,6,21)
capital=10000000
results_file='data_equity_file.csv'
verbose=False
assets=[
'AAL', # American Airlines Group, Inc.
'GOOG', # Apple Inc.
'UAL', # United Airlines Holdings, Inc.
'AMD', # Advanced Micro Devices, Inc.
'MSFT' # MICROSOFT
]
# Use True if you want debug information for your Trader
#sets the backtest setup
period=se.DAILY
bts=se.backtest.set(assets,prestart,start,end,period,capital,results_file,verbose)
if se.backtest.checkBTS(bts): # check if the backtest setup is ok!
print('Backtest Setup is Ok!')
else:
print('Backtest Setup is NOT Ok!')
se.connect()
# Running the backtest
df= se.backtest.run(trader,bts)
# run calls the Trader. setup and trade (once for each bar)
# evaluates the backtest results
se.backtest.evaluate(df)
install and import mt5se and MetaTrader5
get financial data
create direct control trading robots
create [Simple] Trader classes based on inversion of control
backtest Autonomous Traders
deploy autonomous trader to run on simulated or real Stock Exchange accounts
create Autonomous Traders based on Artifical Intelligence and Machine Learning