-
-
Notifications
You must be signed in to change notification settings - Fork 104
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
Deadlock when using helper.Duplicate function in the indicator package #243
Comments
Hi! Thank you for filling this issue. Yes, looking at your example code, by design, it will get into a deadlock, let me explain why, and how to get around that: Imagine helper.Duplicate() creates two copies of an input channel. It expects these copies to be used in a strict order:
If your code doesn't follow this order (e.g., trying to use outputs[1] before outputs[0]), it creates a "deadlock". From duplicate.go: for n := range input {
for _, output := range outputs {
output <- n
}
} In your example, One way to get around this is through the helper.Buffered(). It will allow you have a set a buffer for the channel, so that it won't block immediately. For example, in your case, if you use the helper.Buffered(), it will no longer get into a deadlock: package main
import (
"fmt"
"github.com/cinar/indicator/v2/helper"
)
func main() {
input := helper.SliceToChan([]float64{-10, 20, -4, -5})
outputs := helper.Duplicate(input, 2)
outputs[0] = helper.Buffered(outputs[0], 4)
outputs[1] = helper.Buffered(outputs[1], 4)
fmt.Println(helper.ChanToSlice(outputs[0]))
fmt.Println(helper.ChanToSlice(outputs[1]))
} I am very much interested in learning more about your use case. |
I noticed in your rsi_strategy.go code: // Report processes the provided asset snapshots and generates a report annotated with the recommended actions.
func (r *RsiStrategy) Report(c <-chan *asset.Snapshot) *helper.Report {
//
// snapshots[0] -> dates
// snapshots[1] -> Compute -> actions -> annotations
// snapshots[2] -> closings[0] -> close
// -> closings[1] -> Rsi.Compute -> rsi
//
snapshots := helper.Duplicate(c, 3)
dates := asset.SnapshotsAsDates(snapshots[0])
closings := helper.Duplicate(asset.SnapshotsAsClosings(snapshots[2]), 2)
rsi := helper.Shift(r.Rsi.Compute(closings[1]), r.Rsi.IdlePeriod(), 0)
actions, outcomes := strategy.ComputeWithOutcome(r, snapshots[1])
annotations := strategy.ActionsToAnnotations(actions)
outcomes = helper.MultiplyBy(outcomes, 100)
report := helper.NewReport(r.Name(), dates)
report.AddChart()
report.AddChart()
report.AddColumn(helper.NewNumericReportColumn("Close", closings[0]))
report.AddColumn(helper.NewNumericReportColumn("RSI", rsi), 1)
report.AddColumn(helper.NewAnnotationReportColumn(annotations), 0, 1)
report.AddColumn(helper.NewNumericReportColumn("Outcome", outcomes), 2)
return report
} I’m curious about why it’s possible to use snapshots without strictly following a sequential order here. Additionally, if I don’t know the exact buffer size needed, what would be a recommended approach to avoid potential deadlocks? |
I’m currently using this library to calculate indicators and select stocks with expected patterns after the daily market close for short-term trading. Since the Chinese stock market operates on a T+1 settlement basis, this approach aligns well with my needs. |
Sorry for my slow response.
I would suggest starting with 2, which should give enough window for a single pass to occur without being blocked. Setting it to the size of the data makes it behave similar to the slices in v1 of this library. I hope this helps.
This is very similar to my use case also. I have a modified version of the indicator-bactest using my favorite and custom strategies, and generating me reports at the end of each day. Planning to develop a cleaner UI, along with some stock tracking, and portfolio tracking functionality, probably during the holidays. |
Thank you for the suggestion! Starting with a buffer size of 2 makes sense, and I’ll try that in my implementation. |
Hello,
I encountered a deadlock issue when using the helper.Duplicate function in the indicator package. Here is the code I used to reproduce the issue:
Problem:
When running this code, it results in a deadlock. I expected the helper.Duplicate function to allow me to duplicate the input channel without causing a deadlock.
Environment:
Go version: go version go1.23.0 windows/amd64
Indicator version: github.com/cinar/indicator/v2 v2.1.7
Could you please take a look? I’d appreciate any guidance or suggestions to resolve this.
Thank you!
The text was updated successfully, but these errors were encountered: