Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logging Orders #53

Closed
bscully27 opened this issue Mar 22, 2020 · 7 comments · Fixed by #200
Closed

Logging Orders #53

bscully27 opened this issue Mar 22, 2020 · 7 comments · Fixed by #200
Labels
API Needs API-related discussion enhancement New feature or request

Comments

@bscully27
Copy link

bscully27 commented Mar 22, 2020

Desired Behavior

To dig into each backtest order, specifically to evaluate target prices which I don't believe are working correctly or I'm not calling properly. Didn't see an example in the docs.

I tried adding self.orders to _broker.log but without success - the idea was use copy.copy(self.orders) in backtesting.py for a PIT (point in time) snapshot.

So 2 points I'd like addressed:

  1. How to properly set target prices.
  2. How to enhance the logs with more Order granularity.

Additional Log Attempt

In class _Broker.next(), I called this function when opening or closing a position.

for example in class _Broker.next():
        if entry or orders._close:
            self._update_order_log(self.orders, i)
where:
    def _update_order_log(self, order, i):
            self.log.order_info[i] = copy.copy(order)

then in class _Broker:

    class _Log:
        def __init__(self, length):
        ...
        self.order_info = {k: '' for k in range(length)}

Steps to Reproduce

class SmaCrossTarget(Strategy):
    def init(self):
        self.sma1 = self.I(SMA, self.data.Close, 2)
        self.sma2 = self.I(SMA, self.data.Close, 6)
        self.Close = self.data.Close
        
    def next(self):
        if (self.sma1[-2] < self.sma2[-2]  and  self.sma1[-1] > self.sma2[-1]):
            self.buy(tp=self.Close[-1]*1.05)
        elif (self.sma1[-2] > self.sma2[-2]  and  self.sma1[-1] < self.sma2[-1]):
            self.sell()

GOOG = GOOG.head(40)
bt = Backtest(GOOG, SmaCrossTarget, cash=1000, commission=.001)
result = bt.run()
result._trade_data.dropna(subset=['Entry Price']).head(3)
               Equity  Exit Entry  Exit Position  Entry Price  Entry Direction  Exit Price Exit Comment      P/L  Returns
2004-08-30 1,030.0300         nan            nan     105.2800          -1.0000         nan                   nan      nan
2004-09-09 1,021.8743      7.0000        -9.4890     102.5300           1.0000    102.5300          NaN  25.0957   0.0244
2004-09-28 1,154.8585     14.0000         9.9880     121.3000          -1.0000    121.3000          NaN 186.4511   0.1825

The 3rd line should have been closing the position when target_price was hit.

Additional info

  • Backtesting version: 0.1.6
@lkmh
Copy link

lkmh commented Apr 18, 2020

Is the Entry Direction column not longer available ?

@kernc
Copy link
Owner

kernc commented Jul 15, 2020

This was overhauled in #47 (released in 0.2.0), rendering this issue obsolete.

The new way to access individual trades data is:

stats = bt.run()

stats._equity_curve  # equity/drawdown data
stats._trades        # trade data

@kernc kernc closed this as completed Jul 15, 2020
@kernc kernc added the duplicate This issue or pull request already exists label Jul 15, 2020
@bscully27
Copy link
Author

I'm curious about orders though, not trades.

@kernc kernc changed the title Backtest Debug - Check Orders Logging Orders Jul 17, 2020
@kernc
Copy link
Owner

kernc commented Jul 17, 2020

@bscully27 You could always continue to log orders yourself: 😁

class MyStrategy(Strategy):
    def init(self):
        self.orders_log = []
        ...

    def buy(self, *args, **kwargs):
        super().buy(*args, **kwargs)
        self.orders_log.append(self.orders[-1])

    def next(self):
        ...
        self.buy(...)

stats = Backtest(...).run()
orders_placed = stats._strategy.orders_log

@kernc kernc reopened this Jul 17, 2020
@kernc kernc added API Needs API-related discussion enhancement New feature or request and removed duplicate This issue or pull request already exists labels Jul 17, 2020
@albertwh1te
Copy link

Is the Entry Direction column not longer available ?

@lkmh In fact, you can infer the Entry Direction with size column, if size > 0 Entry Direction is long otherwise is short.

@s-kust
Copy link

s-kust commented Nov 17, 2020

Dear author, the information about accessing individual trades and orders is very useful and even essential. Would you please make it easier to find? I mean, add this information into the manuals and examples.

When I tried the following code
def buy(*args, **kwargs): super().buy(*args, **kwargs) self.orders_log.append(self.orders[-1])

I got an error

RuntimeError: super(): no arguments

I have found the solution here.

This works better:
def buy(self, *args, **kwargs): super().buy(*args, **kwargs) self.orders_log.append(self.orders[-1])

@kernc
Copy link
Owner

kernc commented Dec 16, 2020

There's some new related discussion in #197.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API Needs API-related discussion enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants