Helper questions - custom strategy example #159
Replies: 6 comments 23 replies
-
Hi! Definitely very much curious to hear your thoughts after using the library. Let me see if I can help answering your questions. Question 0: Most helper functions, except the Drain and ChanToSlice are async in nature. They strat a go routine, and return a channel for their output. Drain and ChanToSlice are synchronous as they block and consume the given channel until it ends. In your example, as soon as you put the ChanToSlice, it must be blocking things. As the function won't return, no one can consume from the returned Action channel, the Map function on snapshot won't continue. Dealing with the channels in this way is a little tricky. I was getting stuck a lot at the beginning also. Question 1: You are correct. My initial design was Map to act as a mapping function, taking one channel of a type, and returning a new channel with a different type. Like taking a channel of Snapshot and returning a channel of Action. Operate takes 2 input channels, and return an output channel. It does some operation using the given 2 input channels to produce the output channel. Operate 3 takes input channels. I want to merge them all under a single helper function but I couldn't find a nice way of doing so yet. I hope these helps you to proceed further. |
Beta Was this translation helpful? Give feedback.
-
My first guess is that the following section is the issue here.
'''
helper.Skip (u, s.Donchian. IdlePeriod( )) = helper. Skip (m, s. Donchian.
IdlePeriod()) = helper . Skip(l, s.Donchian. IdlePeriod( ) )
'''
The Donchian indicators outputs U, M, L won't produce any values through
the IdlePeriod (I need a better name for this). So you don't have to Skip
any values at this stage.
However, you do need to Skip IdlePeriod worth of values from both Closings
and Volumes to align them with the U, M, L.
I'll try to put this on a repl and respond today.
…On Tue, Jun 18, 2024, 7:43 AM heiningair ***@***.***> wrote:
Another finding:
It also works if i only compute the macd like so:
func (s *TestStrategy) Compute(c <-chan *asset.Snapshot) <-chan strategy.Action {
snapshots := helper.Duplicate(c, 1)
closings := asset.SnapshotsAsClosings(snapshots[0])
// MACD indicator
macdLine, signalLine := s.Macd.Compute(closings)
macdLine = helper.Skip(macdLine, s.Macd.IdlePeriod())
signalLine = helper.Skip(signalLine, s.Macd.IdlePeriod())
actions := helper.Operate(macdLine, signalLine, func(macdValue, signalValue float64) strategy.Action {
action := strategy.Hold
if macdValue > signalValue {
action = strategy.Buy
} else if macdValue < signalValue {
action = strategy.Sell
}
return action
})
return actions
}
So it is about combining multiple computations?! The channel for the
second calculation seems to get drained and is then empty before the second
calculation.. is that possible?
—
Reply to this email directly, view it on GitHub
<#159 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AANMH3EQDYIICBPRADWH2RTZIBBRXAVCNFSM6AAAAABJMPI7G6VHI2DSMVQWIX3LMV43SRDJONRXK43TNFXW4Q3PNVWWK3TUHM4TQMBXGI4TM>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
Let me start by answering #159 (reply in thread) first. I think the not consuming issue is most likely due to the data that you're using. In my case, I used the brk-b.csv file that is used in most of the tests. It goes until 2023-11-29. However the Backtest by default only checks for the data since Now() - 30 days, so when you run Bactest on this, it doesn't produce any results. (I guess I probably need to use the LastDate() from the Repository, and not the current date. I'll probably fix this, as I agree that it is confusing.) backtest := strategy.NewBacktest(repository, "output")
backtest.LastDays = 365 I also had to make a few minor changes in your code. Most specifically around not Skipping the results of the Donchian indicator, but Skipping the Volumes and Snapshots[2] to align them correctly with those. volumes = helper.Skip(volumes, s.Donchian.IdlePeriod())
snapshots[2] = helper.Skip(snapshots[2], s.Donchian.IdlePeriod()) Here is the modified code: Issue: #160 (comment) |
Beta Was this translation helpful? Give feedback.
-
Regarding #159 (reply in thread) I was able to also fix it by skipping the highPrices and lowPrices by s.Macd.IdlePeriod() to align with the results of the s.Macd. // Skipping highPrices and lowPrices to align with the MACD results
highPrices = helper.Skip(highPrices, s.Macd.IdlePeriod())
lowPrices = helper.Skip(lowPrices, s.Macd.IdlePeriod()) Changed code is here: It sounds like I need to add more documentation, or perhaps a guide for writing the strategies, and emphasis how the IdlePeriod should be used. I see that it is a confusing thing at this point. What do you think? |
Beta Was this translation helpful? Give feedback.
-
Thank you for the feedback. I am on a trip so I won't be able to act on
this earlier than next week, but I do acknowledge that a helper function to
help synchronize multiple indicators will be handy.
For now, I would suggest using the strategies and not directly the
indicators if you are aiming to combine multiple strategies together.
Strategies are defined such that you don't have to worry about the periods,
as they will simply emit a Hold signal until they have enough data.
I have some helper strategies, such as the All, Or, Majority, etc. They can
make it easier to combine multiple strategies, however, you can also easily
have your own custom strategy to use them also.
Please let me know if that would work for you.
…On Mon, Jul 8, 2024, 9:55 AM heiningair ***@***.***> wrote:
Good day everybody..
Does that all mean that the library like it is right now is not really
built to combine multiple indicators into larger custom strategies?
I also really like how this lib is making use of the channels, but the
side effects of that (figuring out the correct periods.. not being able to
debug or test the channel population..) make it currently unusable for my
purpose of combining multiple indicators into one custom strategy.
A reference to what i mean would be this here:
https://github.com/twopirllc/pandas-ta
There you can set up cutom strategies by simply defining all the contained
indicators for example.
Is this similar to how it was planned for version 2?
—
Reply to this email directly, view it on GitHub
<#159 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AANMH3CWQYKVNIYV4MWHR43ZLJAWFAVCNFSM6AAAAABJMPI7G6VHI2DSMVQWIX3LMV43SRDJONRXK43TNFXW4Q3PNVWWK3TUHM4TSOBUGQYTQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
Hello Cinar, Is there still the plan to build a helper function to help synchronize multiple indicators within one custom strategy? |
Beta Was this translation helpful? Give feedback.
-
Hi,
Currently I play around with the V2 version of this library, to figure out how to propperly work with the helper functions.
I build the following test strategy to try out my assumptions:
As you can see in the Compute(), I simply duplicate the incoming channel once (even if not necessary, just for testing it).
In this case, it works fine!
For the first question lets assume the following:
Simply adding another consumer (helper.ChanToSlice() producing a slice from the channel) and increasing the duplication to 2
Question0: Why would this break the strategy? It hangs forever on the helper.ChanToSlice()... Why wouldnt this work?
Question1: I assume the helper.Map method would simply map through all the values in the given channel. If there is this Map function, why is there an Operate and Operate3 needed? Cant the same be acchieved with both?
... will add more questions later. Thanks in advance for clarifying 💯
Beta Was this translation helpful? Give feedback.
All reactions