@Taewoo-Kim said in Charts & TradeID:
Are only completed trades shown in the chart? (i.e. open positions don't show?)
Currently, I am passing a tradeid (generated by str(uuid.uuid4())[:8]) to every order, so that I can keep references to them in an internal dict. If order is long, i would call self.sell(tradeid=some_tradeid). I've noticed in other forum posts that this isn't how people close out their positions. Is my understanding incorrect?
tradeid has no specific requirements. It is just an identifier. It would seem simpler to use something like mytradeid = itertools.counter(1) and then use mynewtradeid = next(mytradeid) to have a unique reference which is a lot more palatable for human consumption. But any tradeid will actually do.
If you use the tradeid and want to undo a buy(tradeid=x), you should either do sell(tradeid=x). Of course sell doesn't guarantee you close a position unless you specifiy the same size or have a sizer that does it for you. You may also use close(tradeid=x), becauseclose` calculates the right size for you.
TypeError: unsupported operand type(s) for /: 'LinesOperation' and 'LinesOperation'
The error is generated because you, likely, are not using this:
from future import division
and the code is likely being run under Python 2.7.x (a chain of assumptions here)
That means that the / operation is using the old division style. This was also uncovered by another use case a few days ago and support for old style division has been added to the development branch.
This other error
---> 14 self.lines.RET = math.log(self.data.close) - math.log(self.data.close[-1])
happens because the statement is wrong. math.log is not a built-in operation and cannot be overridden. Furthermore, during the __init__ phase, one uses de delay notation which would be self.data.close(-1) (notice the round parenthesis rather than the square brackets)
This is a calculation which has to happen in next.
In any case, backtrader already contains an Analyzer which calculates logarithmic returns. It defaults to do so using the same timeframe as the data under analysis. But you can for example calculate weekly logarithmic returns of daily data.
See Docs - Analyzers Reference and look for LogReturnsRolling. It doesn't calculate the sign, but you can probably simply extend it to do so.
first need to reverse those ticks because lower ticks have an old timestamp.
Your ticks are in the wrong order. The resampling process can only work forward. That's the reason your ticks are not being resampled.
The more recent timestamps are at the top of the file and most of the world (Yahoo being an exception) works with files which have the more recent timestamps at the bottom.
%m is for months with 2-digits. See: [Python Docs - Basic date and time types](file:///D:/dro/99-misc/docs/devel/python-2.7.10-docs-html/library/datetime.html#module-datetime). Section: 8.1.7. strftime() and strptime() Behavior
Available with this commit in the development branch: https://github.com/mementum/backtrader/commit/aba90a3ff4e115e3373ea15389410adf10f2b4cf
The regular IB functionality doesn't seem broken by these changes.
It may be the same root cause as spyder and other shells which take over the initialization and prevent multiprocessing from working. Some references:
OptReturn instances are returned instead of Strategy instances. The results from cerebro.run are documented here: Docs - Cerebro in the section Returning the results
cerebro returns the instances of the strategies it created during backtesting. This allows to analyze what they did, because all elements in the strategies are accessible:
result = cerebro.run(**kwargs)
The format of result returned by run will vary depending on whether optimization is used (a strategy was added with optstrategy):
All strategies added with addstrategy
result will be a list of the instances run during the backtesting
1 or more strategies were added with optstrategy
result will be a list of list. Each internal list will contain the strategies after each optimization run
Edited the snippet from above to reflect that the correct usage is with date2num (obviously)
Of course using the If from backtrader allows for much more complex scenarios. The 1 + boolean in the snippet was just meant to solve the hypothetical case presented above (1 until date x, 2 from that point onwards)
@Taewoo-Kim said in Backtrader Issues & What's wrong with these tactics?:
Completely noob question - For forex using Oanda as broker.. How do I realistically model commission on Cerebro? (I know the spread is built-in, which I get through the feed)
You cannot. As you point out: it is built in the spread. There is no way to separate it in real life and there cannot therefore be a way to simulate that.
Is there a way to tell (in next() or another predefined method) if the end of the data feed has been reached?
Your strategy will stop calling next and will call stop
Suppose i have a datafeed that I use pandas to resample in 1 minute time frame. And because of volume issues, instead of using cerebro.resampledata(), i want to use pandas to resample to 3 minute time frame. Do I need to pass this pandas resampled data by calling cerebro.resampledata() or cerebro.adddata()? And what timeframe/compression timeframe parameter do I need to add (since it's already resampled in pandas)? Is it bt.TimeFrame.Minutes / 3?
If you don't want to resample in backtrader, don't use resampledata, which means you use adddata. You should tell the platform that your data has a combination of Minutes and 3
Currently, im taking the average (ask + bid / 2) to calculate OHLC for both price and via pandas. What is the fundamental problem with using the average to write your algo? I would think that it might be smarter to calculate long entry position based on ask price & volume... and short position on bid price / volume, but this would mean keeping "two" copies of data stream
If your assumption about the slippage isn't that bad, using the MIDPOINT should be fine. Slippage will get you below/above the BID/ASK prices and therefore give you a good approximation.
The only thing I would guess is that creating the stop limit order "gives" hints to the broker... who might be using it against you if their not None-Dealing-Desk broker.
If you are worried about that, you should be operating with a different broker and probably a different market altogether.
There is no need for logic there and that's why there is none. The entry order (aka main side) is protected automatically with a stop-loss side and a take-profit side (the high/low side depends on the direction entry), which are only active if the entry order is executed.
Once the stop-loss/take-profit sides become active, the execution of any of them automatically cancels the other.
If you decide to exit the market with an unrelated order, you have to manually cancel any of the sides (the other will be cancelled automatically) as in
self.cancel(order_stop_loss_side) # this automatically cancels the take-profit side too