Giter VIP home page Giter VIP logo

kieran-mackle / autotrader Goto Github PK

View Code? Open in Web Editor NEW
856.0 42.0 197.0 15.68 MB

A Python-based development platform for automated trading systems - from backtesting to optimisation to livetrading.

Home Page: https://kieran-mackle.github.io/AutoTrader/

License: GNU General Public License v3.0

Python 99.41% JavaScript 0.59%
algorithmic-trading algo-trading forex crypto stocks finance investing trading trading-strategies trading-bot

autotrader's People

Contributors

github-actions[bot] avatar ihopethiswillfi avatar jmcph4 avatar kieran-mackle avatar pboachie avatar raptoravis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

autotrader's Issues

Backtest results changed after version upgrade

Describe the bug
I had different backtest results after I've upgraded Autotrader from 0.6.5 to 0.6.6.

In the backtest in version 0.6.6:
- Only the first position was opened and all the signals, coming after that, were canceled.
- The first position has been stayed open until the end
- NAV passed immediately to $-208923.93 after I opened first Position (see screenshot below)

image

In the backtest in version 0.6.5:
- Everything was OK

image

Backtest results in version 0.6.5

Start date:              Jan 05 2021 16:00:00
End date:                Jun 03 2022 20:00:00
Starting balance:        $32000.0
Ending balance:          $39126.36
Ending NAV:              $39127.56
Total return:            $7126.36 (22.3%)
Total no. trades:        99
Total fees:              $194.136
Backtest win rate:       44.4%
Maximum drawdown:        -11.66%
Max win:                 $1940.71
Average win:             $526.24
Max loss:                -$2181.52
Average loss:            -$291.42
Longest win streak:      5 trades
Longest losing streak:   8 trades
Trades still open:       1
Cancelled orders:        59

Backtest results in version 0.6.6

Start date:              Jan 05 2021 16:00:00
End date:                Jun 03 2022 20:00:00
Duration:                514 days 04:00:00
Starting balance:        $32000
Ending balance:          $32000
Ending NAV:              $-208923.93
Total return:            $0 (0.0%)

 No trades closed.
Trades still open:       1
Cancelled orders:        158

My strategy params

NAME: 'SMA2 Strategy'
MODULE: 'SMA2'
CLASS: 'SMA2'
INTERVAL: 'H1'
PERIOD: 40
RISK_PC: 100
SIZING: 'risk'
PARAMETERS:
   
  # Exit level parameters
  RR: 6
WATCHLIST: ['XAG_USD',]

Strategy signals

  • to initiate a Long position I set this code:

       new_order = Order(direction=1)
    
  • For Short position I set this code:

      new_order = Order(direction=-1)
    
  • Take profit or Stop Loss when it reaches 6%

Periodic Live trading works for only one Instrument

Describe the bug
I had an issue when I run the script in live trading for more than one Instrument. Only the last Instrument in Watchlist variable is traded.

To Reproduce

Configuration:

  • WATCHLIST: ['XAG_USD' ,
    'EUR_USD' ,
    'AUD_USD']

  • Trading mode : periodic

When I run the script I see that 3 bots have been assigned to the three instruments, However, only the last one is traded
In fact, the function generate_signal() is called once in each interval (I added a print inside this function to check which Instrument is traded)

Below the console output when the script is running in live trading:
`AutoTraderBot assigned to trade XAG_USD with oanda broker using Difkara Mean Reversion Strategy.

AutoTraderBot assigned to trade EUR_USD with oanda broker using Difkara Mean Reversion Strategy.

AutoTraderBot assigned to trade AUD_USD with oanda broker using Difkara Mean Reversion Strategy.
Update bot for instrument AUD_USD
Instrument AUD_USD , MACD Value= 25.1`

I fixed this by adding a for loop inside autotrader.py in line 1175
for bot in self._bots_deployed:

image

Could you please add that line in the upcoming release ?

Thanks,

TypeError: find_swings()

Hi,
Running indiview with:

from datetime import datetime
from autotrader import AutoData, AutoPlot, indicators
from finta import TA

get_data = AutoData(data_source="yahoo")

instrument = 'EURUSD=X'
data = get_data.fetch(
instrument=instrument,
granularity='1h',
start_time=datetime(2021, 1, 1),
end_time=datetime(2021, 3, 1),
)

rsi = TA.RSI(data, 12)
rsi_divergence = indicators.autodetect_divergence(ohlc=data, indicator_data=rsi)

produces:

Traceback (most recent call last):
File "autotrader-demo-main/indiview.py", line 19, in
rsi_divergence = indicators.autodetect_divergence(ohlc=data, indicator_data=rsi)
File "/home/kgori/.local/lib/python3.8/site-packages/autotrader/indicators.py", line 730, in autodetect_divergence
indicator_swings = find_swings(indicator_data, data_type="other")
TypeError: find_swings() got an unexpected keyword argument 'data_type'

plotting error

i tried running the demo as is,it runs perfectly until it reaches plotting where it raises

AttributeError: unexpected attribute 'plot_width' to figure, similar attributes are outer_width, width or min_width.

i guess this has to do with the old version of bokeh Autotrader is using

dydx Connectivity

Hi there,
I am looking to live trade with dydx, but when I am attempting to connect and run a basic algorithm, I am getting errors.

The first one is: AutoData is not defined. I fixed this by importing the class in the dydx/broker.py file.

The next one is related to the data feed. The system exits right after the prompt "Please specify a data feed" shows up.

Any help would be greatly appreciated!
Jamie
Capture

Support for multi-time frame data

Is your feature request related to a problem? Please describe.
Support for allowing to read in 2+ different time frames at a time, this helps if you are building a strategy around higher time frame indicators but want to trade on a lower time frame.

Describe the solution you'd like
Similar to watchlist which allows for a list of product codes, allow for a list of time frames.

Describe alternatives you've considered
I realise you can just get the data manually and load it manually in the init of your strategy, but loading the data in your runfile will overwrite the data you specified in the YAML, so allowing for additional time frames, or another variable for supplementary data would be ideal.

Additional context
n/a

Add brokerage fees

Is your feature request related to a problem? Please describe.
The profit and drawdown can be more accurate because the fees for each trade (open and close) are not taken into account.

Describe the solution you'd like
The possibility to add a custom value in the parameters for the broker fees depending on the type of entry (for example if the entries are in market and the exits in limit have the possibility to have different fees).
It would also be great to have the total number of fees paid in the backtest result like the example below.
Capture

PS : love your work!

Virtual broker requires reason arg for cancel_pending_order method

I noticed that the virtual broker cancel_pending_order method had a mandatory reason parameter, but the Oanda broker does not have this parameter.

I think this means a strategy that wants to call self.broker.cancel_pending_order(order_id=123) would work in live trading but not in backtesting because the method signatures are different.

If the virtual_broker.py cancel_pending_order function had reason=None then this would solve the issue.

References:

  • autotrader/brokers/virtual/virtual_broker.py function cancel_pending_order(self, order_id, reason)
  • autotrader/brokers/oanda/Oanda.py function cancel_pending_order(self, order_id)

Backtests for Intraday Strategies which involve exiting trade at particular time before auto square off

Is your feature request related to a problem? Please describe.
Not sure whether it is request but would like to know how we can perform backtests for intraday strategies.
Time frame 5 min something like that. Yfinance gives data for intraday only for 2 months (1 min or 5 min data).

Describe the solution you'd like
Facility to run intraday backtests using say 5 min timeframe data. Solution is to have local csv files and call them in pandas and use for analysis.

Describe alternatives you've considered
Download csv data and run backtest using that data

Additional context
Brokers provide 5 min data for 60 days only if we want more data we need to run in loop for every 2 months.
And only 5 years data is available for zerodha like Indian broker

Time misalignment detected

Describe the bug
I encountered a Time misalignment detected on live trading mode. It seemed to be causing trades to be wrongly opened.

To Reproduce
Steps to reproduce the behavior:
I'm not too sure how to reproduce but I've upgraded my autotrader version to the latest. Waiting to see if this happens again.

Expected behavior
I'm not too sure if this warning/error caused the trades to be wrongly opened.

Screenshots
Screenshot 2021-12-28 at 1 33 05 PM

Version of AutoTrader being used
Using version 0.5.11

Additional context
N/A

Export backtest results

Is your feature request related to a problem? Please describe.
While it is handy to have the plot to manually review the backtest results it would also be very useful to analyse the trading results automatically using a script to extract insights.

Describe the solution you'd like
Export backtest results in a dataframe similar to what is displayed in the plot, with the additional functionality of being about to add additional features, possibly stored in the exit dictionary. This would be very beneficial for optimisation of strategies.
Something similar to this possibly:

Datetime Entry Price Exit Price Result Type Order type Stop loss Take profit Custom feature
12:12 12:12:00 $13.2 $14 Win Long market $13 $14 0.123
12:15 12:12:00 $14 $15 Loss Short market $15 $13 1.2

Describe alternatives you've considered
I am not sure if this is already possible I had a look but couldn't see anything around export results, I apologise if I missed it in the documentation.

Additional context
n/a

Rithmic API

Request the addition of the Rithmic API as a broker. Could use this bot to trade more than crypto.

Dependencies should be specified via Pip

Is your feature request related to a problem? Please describe.
Whilst not a strict necessity for Python projects, it's fairly conventional to specify dependencies via Pip, the de facto standard package manager for Python. This is achieved via a requirements.txt manifest file conforming to the expected format.

Describe the solution you'd like
A requirements.txt file located in the project root containing the necessary dependencies extracted from the existing setup script:

AutoTrader/setup.py

Lines 52 to 78 in 9478b62

install_requires=[
"numpy >= 1.20.3",
"pandas >= 1.3.4",
"art >= 5.7",
"PyYAML",
"bokeh >= 2.3.1",
"scipy >= 1.7.1",
"finta >= 1.3",
"tqdm>=4.64.0",
"importlib-resources",
"Click",
"requests",
],
extras_require={
"dydx": ["dydx-v3-python"],
"ccxt": ["ccxt"],
"oanda": [
"v20 >= 3.0.25.0",
],
"ib": [
"ib_insync >= 0.9.70",
],
"yfinance": [
"yfinance >= 0.1.67",
],
"dev": ["black"],
},

Describe alternatives you've considered
We could separate out the different profiles (i.e. distinguish between production and development requirements) but this seems overengineering at the moment.

Additional context
None.

Unsure of how to define the IB connection parameters

Hello!

I am trying to use autotrader with IB, and I can't seem to get it to connect to the InteractiveBroker Gateway. When I specify the feed=ib and broker=ib, the runfile.py errors that it can't connect. Originally, I was running my IB GW on port 5000 as that is the default. I tried defining "HOST" and "PORT" in my GLOBAL.yaml, but nothing I define there would actually point the connection to another host/port. I am certain that I am reading in the GLOBAL.yaml because if I comment out the IB section, the script bombs asking for HOST to be defined. I moved my IB GW from 5000 to 7497 since that is what the script appears to be asking for, and I was able to get past the "connection refused" errors. However...

Once I could get runfile.py to communicate with the IB GW, the script errors with a timeout. I suspect it may not understand that it needs to speak SSL to the IB GW? But I don't know if that can be defined.

My question is this. Can you give a sample config file for the IB section of the GLOBAL.yaml? I'd like to know what I can set so I can tweak it to work.

Also, great job on everything so far. I don't know what you consider to be a good strat, but I have written one backtesting over 200% in 2 years. I am happy to share it with you privately.

Docs are down

Describe the bug
Read the Docs link are currently down for the documentation.

To Reproduce
Steps to reproduce the behavior:

  1. Go to https://py-autotrader.readthedocs.io/en/latest/

Expected behavior
Read the docs :P

Screenshots
image

Version of AutoTrader being used
n/a

Additional context
n/a

Local Sql Lite DB

Hi, first of all what you did with this repo is really impressive. It will help lot of people to research & backtesting on stock market.

I'm trying to create charts using data from local db. I've tick level data in sqllite db. Trying to understand how to provide that as input to add_data

Currently I'm working on pandas dataframes to analyze, so this is how I access to data
df_data[symbol] = pd.read_sql("SELECT * FROM {} where time BETWEEN {} and {}".format(tradesTableName,tickerStartDateTimestamp,tickerEndDateTimestamp), con=db)

Any suggestions on how to plot the data?

Thank you very much for your time.

Cheers!
Vamsi

Risk per trade

Is your feature request related to a problem? Please describe.
Right now, if I were to set 1% risk per trade, I get a lot of cancelled trades if the stop losses is tight. What happens is it tries to max out the margin based on the absolute loss for that trade. The trade does not go through because my account's leverage is not high enough.

Describe the solution you'd like
Can we modify the risk approach that does not max out the position sizing based on the 1% risk alone but take into account the leverage of the trading account. So the open trade could risk < 1% (based on my earlier example), and that's fine.

Describe alternatives you've considered
Indicate a smaller risk per trade amount, which prevents margin from being maxed out.

Additional context
N.A

Telegram support for alerts to buy and signal

Is your feature request related to a problem? Please describe.
Email notifications are bit complicated to manage and Telegram is used worldwide

Describe the solution you'd like
Along with Email, is it possible to send signals to Telegram?

Describe alternatives you've considered
Need to implement forwarding of email signals to Telegram channel or coding for the same.

Additional context
It will be great is Telegram Channel support is implemented.
Adv:

  1. One can send Buy Sell signals along with SL and TARGET and even Quantity based on predefined risk.
  2. Not supported brokers can be handled using Telegram. Code is already there to read Telegram messages from channel suing python and trades can be taken using python.

building-strategy.md is missing PERIOD: 300

Describe the bug
building-strategy.md in /docs/source/tutorials/ is missing PERIOD: 300 which causes a KeyError when running a test
If someone just follows the tutorial without using the demo repo, then it becomes an issue.
Although, this maybe a very minor issue. I just stumbled on it and thought of letting you guys know.

To Reproduce
Steps to reproduce the behavior:

  1. Go to 'building-strategy.md'
  2. Scroll down to 'Strategy Configuration'
  3. Scroll down a little more until you see the code block example for a strategy.yaml
  4. See error

Expected behavior
Expected PERIOD: 300 key/value within the example but is missing. But the demo repository has PERIOD: 300 in it's .yaml file

Screenshots
ScreenShot

Version of AutoTrader being used
N/A (master repository)

Additional context
It is also in 'ReadTheDocs.io

Error encountered while running on Live Mode

Describe the bug
Could not run on Live Mode on Oanda.

Traceback (most recent call last):
  File "runfile.py", line 23, in <module>
    at.run()
  File "/usr/local/lib/python3.8/site-packages/autotrader/autotrader.py", line 218, in run
    self._main()
  File "/usr/local/lib/python3.8/site-packages/autotrader/autotrader.py", line 295, in _main
    bot = AutoTraderBot(instrument, self.strategies[strategy],
  File "/usr/local/lib/python3.8/site-packages/autotrader/autobot.py", line 146, in __init__
    data, quote_data, MTF_data = self._retrieve_data(instrument, self.feed)
  File "/usr/local/lib/python3.8/site-packages/autotrader/autobot.py", line 546, in _retrieve_data
    data = getattr(self.get_data, feed.lower())(instrument,
  File "/usr/local/lib/python3.8/site-packages/autotrader/lib/autodata.py", line 99, in oanda
    data        = self.response_to_df(response)
  File "/usr/local/lib/python3.8/site-packages/autotrader/lib/autodata.py", line 222, in response_to_df
    candles = response.body["candles"]
KeyError: 'candles'

To Reproduce
Here is a copy of my strategy yaml file

NAME: 'MACD Momentum Strategy'
MODULE: 'macd'
CLASS: 'SimpleMACD'
INTERVAL: '5m'
PERIOD: 200
RISK_PC: 1
SIZING: 'risk'
PARAMETERS:
  ema_period_fast: 20
  ema_period_slow: 200
  MACD_fast: 12
  MACD_slow: 26
  MACD_smoothing: 9

WATCHLIST: ['EURUSD=X']

Expected behavior
To be able to run as expected on Live Mode.

Version of AutoTrader being used
Latest.

Any idea what the issue could be?

Can we please get an exact Step-by-Step tutorial of how to set it up with Crypto Exchange?

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

Insufficient margin to fill order when stop loss is set

Describe the bug
I've an issue when I set a stop loss in my strategy:
Situation :

  • stop loss is equal to 6% ( issue still valid in case of different values)
  • result : 0 trade executed --> reason : "Insufficient margin to fill order."

Configuration:

  • RISK_PC: 100
  • SIZING: 'risk'

Backtest configuration:

  • initial_balance=32000,
  • leverage = 1,
  • spread=0.03,
  • commission=0.005

Strategy Exit signals:

If signal == 1:
     stop = self.data.Close[i] * (1 - 0.06)  # self.data.Close[i] is the close price
If signal == -1:
     stop = self.data.Close[i] * (1 + 0.06)

When I've performed some code investigation, I figured out that ;
margin_required is always greater than self.margin_available ( in file broker.py inside _fill_order function )
Example :
margin_required=377116.75920040935 , self.margin_available=32000

This is due to how order.size is calculated in file broker_utils.py inside get_size function :
It seems that when a stop loss is set, the number of units to buy is calculated as follows:

price_distance = abs(price - stop_price)
quote_risk = amount_risked / HCF
units = quote_risk / price_distance

where HCF = 1

I don't understand why the position size is calculated in that way. why we divide it by the price_distance and not just price ?
In my point of view it must always be like this : units = amount_risked/(HCF*price)

Thanks

Indian Broker support example NorenAPI or Zerodha

Is your feature request related to a problem? Please describe.
Support for Indian broker is not yet implemented

Describe the solution you'd like
Implement support for Indian Broker or provide guidelines for supporting different brokers who provide only APIs.
Indian brokers like zerodha have good python module for trading named pykiteconnect
There is also a broker with zero brokerage who provides API and they are developing python module as well
NorenAPI

Describe alternatives you've considered
Self implementation

Additional context
Lot of people in India have started doing Algo Trading but there are very costly solutions for the same.
You have implemented a wonderful module and the documentation is also great.
It will be good to have such implementation for Indian Traders.

KeyError: -1 in find_swings()

Describe the bug
KeyError: -1 when running code below.

To Reproduce

y = pd.Series([5, 10, 3, 5, 3])
swings = autotrader.indicators.find_swings(data=y, data_type='other', n=2)

Version of AutoTrader being used
eg. Using version 0.7.10

Additional context
Error occurs on line 405 in indicators.py:
grad = [swing_data[i] - swing_data[i-1] for i in range(len(swing_data))]

This seems to me like it would always throw an error, because the first iteration will have i==0 and so i-1 will equal -1, which is expected to error.
I would personally write this like:
grad = [swing_data[i] - swing_data[i-1] for i in range(1, len(swing_data))]
this however makes the output shorter by 1 item.

Interactive Brokers

Noted that support for IB was planned, but did not spot any draft implementation

Was thinking of implementing Interactive-Brokers support through using IB-Insync framework for simplicity(mainly using it for stocks), but if you already have something cooking that would save time and effort of course..
https://github.com/erdewit/ib_insync.git

Note that I'm still on a steep learning curve, so things go slow ; )
Thanks for a nice package anyway.

Where is the rolling_signal_list variable defined

Describe the bug
A clear and concise description of what the bug is.
Visual studio code is unable to find the variable caled rolling_signal_list
To Reproduce
Steps to reproduce the behavior:

  1. I am trying to use your divergence indicator in my own code. '...'
  2. What routines do I need to use it?
  3. I have taken ema, classify_swings, find_swings and detect_divergence.
  4. What other code do I need to include for the above routines to work?

Expected behavior
I should be able to use the detect_divergence routine.

My idea behind using the divergence ndicator is to detect when a bearish trend is about to begin. I have a long only machine learning model which works when I need to buy stocks but I need to sell on time. My idea is to detect a bearish divergence. If that happens, I know the price could fall therefore take profit and move on.

Position size not fully filled when I switch position direction

Describe the bug

In backtest, when a new signal is triggered, and it has a different direction than the current open position, the order size, is not entirely filled

Expected behavior
Like with tradingview pine scripts, when I switch position direction, the existing position is immediately closed and a new one is opened with the exact ordered size.

Below, a screenshot of orders history, in which I added two columns about the desired position size (My order size) and current balance

image

Configuration
Position size is calculated manually in each triggered signal
position_size = floor(self.broker.get_NAV()/self.data.Close[i])

Explanation
In the second order, the script has ordered 1310 units, however, only 81 were executed.
Of the 1310 units, 1229 were used to close the open position and the remaining ones have been executed in the new position.

I think that this behavior comes from broker.py in lines 300 to 303

image

I tried to manipulate my order size to close the existing one and entirely fill the new position, but I got errors of insufficient margin

Is there any way to overcome this behavior?

Thanks,

Add Tox support

Is your feature request related to a problem? Please describe.
Tox is a very popular Python development and build automation tool that interfaces well with existing Python tooling and conventions. It would be nice if Tox support was added to the project.

Describe the solution you'd like
Creation of a Tox configuration file in the project root.

Describe alternatives you've considered
N/A

Additional context
None.

IndexError: index 0 is out of bounds for axis 0 with size 0

Traceback (most recent call last):
File "C:\Users\Tomk Vu\Desktop\autotrader-demo-main\runfile.py", line 19, in
at.run()
File "C:\Users\Tomk Vu\AppData\Local\Programs\Python\Python39\lib\site-packages\autotrader\autotrader.py", line 226, in run
self._run_optimise()
File "C:\Users\Tomk Vu\AppData\Local\Programs\Python\Python39\lib\site-packages\autotrader\autotrader.py", line 1266, in _run_optimise
result = brute(func = self._optimisation_helper_function,
File "C:\Users\Tomk Vu\AppData\Local\Programs\Python\Python39\lib\site-packages\scipy\optimize_optimize.py", line 3496, in brute
Jout = np.array(list(mapper(wrapped_func, grid)))
File "C:\Users\Tomk Vu\AppData\Local\Programs\Python\Python39\lib\site-packages\scipy\optimize_optimize.py", line 3568, in call
return self.f(np.asarray(x).flatten(), *self.args)
File "C:\Users\Tomk Vu\AppData\Local\Programs\Python\Python39\lib\site-packages\autotrader\autotrader.py", line 1336, in _optimisation_helper_function
backtest_results = self.analyse_backtest(bot)
File "C:\Users\Tomk Vu\AppData\Local\Programs\Python\Python39\lib\site-packages\autotrader\autotrader.py", line 861, in analyse_backtest
backtest_results['start'] = account_history.index[0]
File "C:\Users\Tomk Vu\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\indexes\base.py", line 5039, in getitem
return getitem(key)
IndexError: index 0 is out of bounds for axis 0 with size 0

Broker interface should be programmatically enforced

Is your feature request related to a problem? Please describe.
A common desire is to extend AutoTrader's functionality to new exchanges (either specific instances of exchanges or entire classes, such as DEXes). In order to do this, new implementations must conform to the broker interface. Unfortunately, this interface, despite having very real expectations on compliant implementations, is not enforced anywhere in the current codebase.

Python purists will argue this is not Pythonic as it attempts to sidestep ducktyping; however, there is clearly confusion surrounding exactly what a broker must look like.

Describe the solution you'd like
At a high level, programmatic enforcement of the broker interface (which exists regardless of enforcement method). Actually achieving this in Python is sadly a best-effort endeavour though.

The least insane solution is very likely an abstract base class. Specifically, by defining abstract methods. Something like the following should suffice:

class Broker(metaclass=abc.ABCMeta):
    @classmethod
    def __subclasshook__(cls, subclass):
        return (hasattr(subclass, 'get_NAV') and 
                callable(subclass.get_NAV) and 
                hasattr(subclass, 'get_balance') and 
                callable(subclass.get_balance) and
                hasattr(subclass, 'place_order') and 
                callable(subclass.place_order) and
                hasattr(subclass, 'get_orders') and
                callable(subclass.get_orders) and
                hasattr(subclass, 'cancel_order') and
                callable(subclass.cancel_order) and
                hasattr(subclass, 'get_trades') and 
                callable(subclass.get_trades) and
                hasattr(subclass, 'get_positions') and
                callable(subclass.get_positions) or
                NotImplemented)

    @abc.abstractmethod
    def get_NAV(self) -> float:
       pass
       
    # etc. ...

Describe alternatives you've considered
Other methods like subclass hooks but these seem ugly and complicated (admittedly my Python knowledge may be lacking here and these might be The One True Way(TM)).

Additional context
None.

Support for stock options trading

Automated trading for stock options

Features to support stock options trading on IBKR

-function to pull options data
-function to analyze options data
-function to make orders on options

Specifiy your own data file should load the data but fails due to variable problem

Describe the bug
When specifying your own data file the AutoTrader initialisation fails due to a variable being referenced before the assignment.

To Reproduce
Steps to reproduce the behavior:

  1. Create a run file with any of the example strategies
  2. add your data file e.g. at.data_file = "ftx_data.csv"
  3. Run the backtesting
  4. See error:
    UnboundLocalError: local variable 'MTF_data' referenced before assignment

Expected behavior
Support for local files

Screenshots
n/a

Additional context
Additionally is there any planned support for MTF local files? Possibly specifying a dictionary e.g.

at.data_files = {'5m': '5m_data.csv', '4h': '4hr_data.csv'}

Or can create a csv that encapsulates this same structure, but might be harder to initialise consistently. Using version 0.4.27

unexpected keyword argument 'strategy_filename'

Hi,
Running demo run_scan.py for autotrader-0.9.1 returns the following error for macd strattegy:

raceback (most recent call last):
File "run_scan.py", line 12, in
at.run()
File "/home/kgori/.local/lib/python3.8/site-packages/autotrader/autotrader.py", line 933, in run
self.add_strategy(strategy_filename=strat_config_file)
TypeError: add_strategy() got an unexpected keyword argument 'strategy_filename'

Thanks

HCF when providing backtesting data files?

Hello,

Firstly, thanks very much for creating this framework, I'm really enjoying focussing on my trading logic instead of the surrounding infrastructure.

When I backtest with my own data files (e.g. EUR_JPY M5, H8 and M timeframes), I noticed that the trade sizing was "off", e.g. a position for EUR_JPY that should have been about 3200 units was being placed for 20 units.

I eventually realised that the sizing function was correct but the HCF it used was set to 1. If it was set to the <account_currency>_JPY rate then the sizing was correct for the given pair.

When using the Oanda broker, it returns the HCF values as part of the REST response for get_price (

negativeHCF = response.body["prices"][0].quoteHomeConversionFactors.negativeUnits
).

So my question is whether I can supply the correct historic HCF data when backtesting with files? If not, do you have any thoughts on where in the framework I should look if I wanted to create a pull request to support this?

Thanks,
Kel

New broker templete

I saw thw new broker templete, but it is missing key information ,

  1. There should what is expected return format for each methods
  2. it does not includes the data loaded info since each broker may have different data methods and different instruments, there should be a possibility of addinfg that

STOCHASTIC Plotting doesn't work

Describe the bug
When using the key STOCHASTIC in the indicators dictionary an error is thrown.

To Reproduce
Steps to reproduce the behaviour:

  1. Create a strategy and create STOCHK and STOCHD
        self.stoch_rsi = TA.STOCHRSI(self.data, rsi_period=6, stoch_period=27)
        self.stoch_rsi_k = TA.STOCH(self.data, period=3)
        self.stoch_rsi_d = TA.STOCHD(self.data, period=3, stoch_period=27)
  1. Create an indicator dictionary something like:
        self.indicators = {
            "RSI": {"type": "RSI", "data": self.stoch_rsi},
            "STOCHASTIC": {
                "K": self.stoch_rsi_k,
                "D": self.stoch_rsi_d,
            },
        }
  1. Run a backtest
  2. See error:

Traceback (most recent call last):
  File "/home/lewis/Projects/trading_bot/runfile.py", line 65, in <module>
    main()
  File "/home/lewis/Projects/trading_bot/runfile.py", line 58, in main
    at.run()
  File "/home/lewis/.pyenv/versions/3.8.9/envs/maxwell/lib/python3.8/site-packages/autotrader/autotrader.py", line 711, in run
    self._main()
  File "/home/lewis/.pyenv/versions/3.8.9/envs/maxwell/lib/python3.8/site-packages/autotrader/autotrader.py", line 1120, in _main
    self.plot_backtest()
  File "/home/lewis/.pyenv/versions/3.8.9/envs/maxwell/lib/python3.8/site-packages/autotrader/autotrader.py", line 971, in plot_backtest
    ap.plot(backtest_dict=bot.backtest_results)
  File "/home/lewis/.pyenv/versions/3.8.9/envs/maxwell/lib/python3.8/site-packages/autotrader/autoplot.py", line 293, in plot
    bottom_figs = self._plot_indicators(indicators, main_plot)
  File "/home/lewis/.pyenv/versions/3.8.9/envs/maxwell/lib/python3.8/site-packages/autotrader/autoplot.py", line 736, in _plot_indicators
    indi_type = indicators[indicator]['type']
KeyError: 'type'

Process finished with exit code 1

Expected behaviour
Plot the two stochastic lines below the chart in one section.

Screenshots
n/a

Version of AutoTrader being used
autotrader==0.6.2

Additional context
Few other questions:

  • Is there any functionality during backtesting to access previous trades? e.g. last 4 trades were losses so use 0.5*RR
  • If the strategy has a lot of triggers it seems to cancel all trades, any idea why this might happen? My thought would be the whole account balance is in use so can't make a new trade without cancelling a previous one, when really it should just not create the new trade and let the old ones run.

Webhook support for signals like tradingview or chartink

Is your feature request related to a problem? Please describe.
Signals / Alerts are currently being sent to email, if AutoTrade can send them to a webhook link it will be great.

Describe the solution you'd like
Whenever a signal comes, AutoTrader must be able to send data in json format to a webhook link.
Data must consist name of strategy, time when signal was generated, candle open high low close OHLCV (V if possible).

{
    "strategy_name": "SMA Momentum",
    "strategy_params": {
      "sma_period" : "44",
      "candle_lookback" : "4",
      "RR" : "1.4",
      "exit_buffer" : "0.2"
    },
    "trading_symbol" : "SBIN.NS",
    "time_frame" : "5min",
     "ohlcv" : {
       "open" : "345",
       "high" : "356",
       "low" : "334",
       "close" : "351",
       "volume" : "2409"
     }
    "triggered_at": "2021-12-24 13:35:05",
    "webhook_url": "http://your-web-hook-url.com"
}

If possible make this customizable like we have in tradingview.
We can add or remove like say timeframe can be removed and we can add symbol or dataprovide like yahoo or oanda.

Describe alternatives you've considered
Reference - chartink.com webhooks
JSON data which is not so useful.

{
    "stocks": "SEPOWER,ASTEC,EDUCOMP,KSERASERA,IOLCP,GUJAPOLLO,EMCO",
    "trigger_prices": "3.75,541.8,2.1,0.2,329.6,166.8,1.25",
    "triggered_at": "2:34 pm",
    "scan_name": "Short term breakouts",
    "scan_url": "short-term-breakouts",
    "alert_name": "Alert for Short term breakouts",
    "webhook_url": "http://your-web-hook-url.com"
}

Additional context
If webhook is provided, it will be easy to integrate a choice of broker order placement code.
Even webhook can be used to send alerts to telegram channel. See below code where I am sending data to a channel using webhook coming from chartink.

from flask import Flask
from flask import jsonify, make_response, request
import requests
from time import sleep
import config_ab as config
import pandas as pd
from urllib.parse import urlencode, quote_plus
from datetime import datetime

app = Flask(__name__)

def telegram_bot_sendtext(message):
    bot_token = '<BOT_TOKEN>'
    bot_chatID = '-100<CHANNEL_ID>'
    data = {
        'text': message,
        'chat_id': bot_chatID,
        'parse_mode': 'MARKDOWN'
    }
    encodedData = urlencode(data, quote_via=quote_plus)

    url = 'https://api.telegram.org/bot' + bot_token + '/sendMessage?' + encodedData
    response = requests.get(url)
    return response.json()


@app.route('/')
def hello_world():
    return 'Chartink testing!!'


def time_check():
    t = datetime.today()
    mis_end_time = datetime(t.year, t.month, t.day, 15, 00)
    if datetime.now() > mis_end_time:
        print("no more intraday trading")
        return True


@app.route('/alertsonly', methods=['POST'])
def alertsonly():

    if not request.is_json:
        return make_response(jsonify({"message": "Request body must be JSON"}), 400)
    body = request.get_json()
    print(body)

    df = pd.DataFrame.from_dict({'symbol': list(body['stocks'].split(
        ',')), 'price': list(body['trigger_prices'].split(','))})
    # print(df)
    table = df.to_markdown(index=False, tablefmt="grid")
    # print(table)
    test = telegram_bot_sendtext(body['alert_name']+'\n'+table)
    print(test)
    return table

I think implementing code to send json to webhook endpoint can be implemented easily since you have already coded for email.

Backtest strategy using Oanda historical data ?

Hi,
I'm trying to backtest your macd demo strategy using Oanda as broker but I'm not able to do so.

Here's steps I've done :

  1. Create a demo account in Oanda , so to receive api v20 access token and account id

  2. Generate keys.yaml in /config folder where I've put previous data (ACCESS_TOKEN, DEFAULT_ACCOUNT_ID)

  3. Modified runfile.py to use oanda as broker at line: at.configure(verbosity=1, show_plot=True, feed='oanda', mode='periodic')

  4. Changed macd.yaml like to match EURUSD Oanda symbol at line : WATCHLIST: ['EUR_USD']

  5. Execute python runfile.py and received this error :

(base) C:\Users\Giacomo\Downloads_AutoTrader\AT_DEMO>python runfile.py
Traceback (most recent call last):
File "C:\Users\Giacomo\Downloads_AutoTrader\AT_DEMO\runfile.py", line 9, in
at.run()
File "C:\Users\Giacomo\anaconda3\lib\site-packages\autotrader\autotrader.py", line 1049, in run
self._main()
File "C:\Users\Giacomo\anaconda3\lib\site-packages\autotrader\autotrader.py", line 1428, in _main
self._assign_broker(broker_config)
File "C:\Users\Giacomo\anaconda3\lib\site-packages\autotrader\autotrader.py", line 1635, in _assign_broker
broker.configure(**account_config, autodata_config=autodata_config)
File "C:\Users\Giacomo\anaconda3\lib\site-packages\autotrader\brokers\virtual\broker.py", line 256, in configure
self._autodata = AutoData(data_config, **autodata_config)
File "C:\Users\Giacomo\anaconda3\lib\site-packages\autotrader\autodata.py", line 82, in init
self.ACCOUNT_ID = data_config["ACCOUNT_ID"]
KeyError: 'ACCOUNT_ID'

Is there something else that I have to set in order to be able to backtest whatever strategy using oanda historical prices ?

Thanks,
Regards
Giacomo

tdameritrade

any chance on getting a tdameritrade version.i'm struggling try to find a way to convert

AutoData docs

**Is your feature request related to a problem? Imagine user wants to use data from other sources for AutoData() for example a data frame from MetaTrader5, how that user could integrate their strategies with auto trader?

Need to update emailing.py related import.

Describe the bug
The emailing.py is moved to autotraders.comms, the code from autotrader.emailing import send_order_summary might not be working in autotrader.bin.email_manager.py

To Reproduce
Steps to reproduce the behavior:

  1. run autotrader.bin.email_manager.py directly.

Expected behavior
Should not show error/

Screenshots
ModuleNotFoundError: No module named 'autotrader.emailing'

Version of AutoTrader being used
0.7.2

Additional context
Add any other context about the problem here.

autodetect_divergence can not be plot

Describe the bug
ValueError: You are trying to merge on datetime64[ns, UTC] and int64 columns. If you wish to proceed you should use pd.concat

To Reproduce

from finta import TA
from autotrader.autodata import GetData
from autotrader.autoplot import AutoPlot
from autotrader.indicators import crossover, cross_values
from autotrader import indicators

get_data = GetData()

instrument = 'EURUSD=X'
data = get_data.yahoo(instrument, '1d',
start_time='2021-01-01',
end_time='2021-04-01')
ema50 = TA.EMA(data, 50)
rsi =TA.RSI(data,12)

rsi_divergence = indicators.autodetect_divergence(data, rsi)

indicator_dict = {
'EMA (50)': {'type': 'MA',
'data': ema50},
'RSI (14)': {'type': 'RSI',
'data': rsi},
'Bullish divergence': {'type': 'below',
'data': rsi_divergence['regularBull']},
}

ap = AutoPlot(data)
ap.plot(indicators=indicator_dict, instrument=instrument)

Screenshots
image

Version of AutoTrader being used
master

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.