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

Force Index Strategy added. #238

Merged
merged 1 commit into from
Oct 18, 2024
Merged

Force Index Strategy added. #238

merged 1 commit into from
Oct 18, 2024

Conversation

cinar
Copy link
Owner

@cinar cinar commented Oct 18, 2024

Describe Request

Force Index Strategy added.

Change Type

New strategy.

Summary by CodeRabbit

  • New Features

    • Updated documentation to reflect enhancements in version 2 of the Indicator Go module.
    • Introduced the ForceIndexStrategy, expanding the library's volume strategies.
    • Added dedicated test data in CSV format for easier validation of indicators and strategies.
    • Streamlined data handling with support for Go channels and helper functions.
  • Bug Fixes

    • Enhanced overall code quality and testability with a minimum of 90% code coverage.
  • Documentation

    • Comprehensive updates to installation, usage instructions, and backtesting functionality.

Copy link

coderabbitai bot commented Oct 18, 2024

Walkthrough

The pull request introduces significant updates to the Indicator Go module, particularly enhancing the README.md to reflect the new features and improvements in version 2. Key updates include the introduction of the ForceIndexStrategy, which is fully documented with associated methods for its configuration and functionality. The library now supports data handling via Go channels and has expanded the list of indicators and strategies, organized by categories. Additionally, new testing files have been added to ensure the functionality of the ForceIndexStrategy, while the overall structure and documentation have been comprehensively revised.

Changes

File Path Change Summary
README.md Complete rewrite to include new features, dedicated test data in CSV, and improved documentation of indicators and strategies.
strategy/volume/README.md Added ForceIndexStrategy type and methods; updated documentation to reference new strategy.
strategy/volume/force_index_strategy.go Introduced ForceIndexStrategy struct with methods for initialization, computation, and reporting.
strategy/volume/force_index_strategy_test.go Added unit tests for ForceIndexStrategy, validating computation and report generation.
strategy/volume/volume.go Modified AllStrategies function to include NewForceIndexStrategy().

Possibly related PRs

🐇 In the garden where data streams flow,
New strategies bloom, watch them grow!
With Force Index, we trade with glee,
Reports and tests, all done with ease.
So hop along, let’s code and play,
For indicators bright, lead the way!
🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@codecov-commenter
Copy link

Codecov Report

Attention: Patch coverage is 97.18310% with 2 lines in your changes missing coverage. Please review.

Project coverage is 93.27%. Comparing base (467323d) to head (1f3c361).

Files with missing lines Patch % Lines
strategy/volume/force_index_strategy.go 98.57% 1 Missing ⚠️
strategy/volume/volume.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #238      +/-   ##
==========================================
+ Coverage   92.93%   93.27%   +0.34%     
==========================================
  Files         169      170       +1     
  Lines        4416     5922    +1506     
==========================================
+ Hits         4104     5524    +1420     
- Misses        253      337      +84     
- Partials       59       61       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Outside diff range and nitpick comments (8)
strategy/volume/volume.go (1)

26-32: Consider maintaining strategy order for consistency

The order of strategies in the returned slice has changed with the addition of the new strategy. While this doesn't affect functionality, it might impact consumers who rely on a specific order of strategies. Consider either:

  1. Adding the new strategy at the end of the slice to maintain the existing order, or
  2. Documenting that the order of strategies should not be relied upon.
strategy/volume/force_index_strategy_test.go (3)

17-37: LGTM: TestForceIndexStrategy is well-structured and comprehensive.

The test function is well-implemented, covering the essential aspects of the ForceIndexStrategy. It reads test data from external files, computes results, and compares them with expected outcomes.

Consider adding a descriptive comment at the beginning of the function to explain its purpose and the strategy being tested. This would enhance the test's documentation and make it easier for other developers to understand the test's intent.


39-55: LGTM: TestForceIndexStrategyReport covers report generation functionality.

The test function effectively checks the report generation and file writing capabilities of the ForceIndexStrategy. Good practices such as error handling and file cleanup are implemented.

Consider the following improvements to enhance the test's robustness:

  1. Verify the contents of the generated HTML file to ensure it contains expected elements or structure.
  2. Use a temporary directory for file operations instead of the current directory to avoid potential conflicts.

Here's an example of how you could implement these suggestions:

func TestForceIndexStrategyReport(t *testing.T) {
	snapshots, err := helper.ReadFromCsvFile[asset.Snapshot]("testdata/brk-b.csv", true)
	if err != nil {
		t.Fatal(err)
	}

	fis := volume.NewForceIndexStrategy()
	report := fis.Report(snapshots)

	// Create a temporary directory for the test
	tempDir, err := os.MkdirTemp("", "force_index_test")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir) // Clean up

	fileName := filepath.Join(tempDir, "force_index_strategy.html")

	err = report.WriteToFile(fileName)
	if err != nil {
		t.Fatal(err)
	}

	// Read the generated file
	content, err := os.ReadFile(fileName)
	if err != nil {
		t.Fatal(err)
	}

	// Verify the content (adjust these checks based on your expected output)
	if !strings.Contains(string(content), "<html>") {
		t.Error("Generated report doesn't contain HTML structure")
	}
	if !strings.Contains(string(content), "Force Index Strategy") {
		t.Error("Generated report doesn't mention Force Index Strategy")
	}
}

This improved version uses a temporary directory, reads the generated file, and performs basic checks on its content.


1-55: Overall, the test file is well-structured and provides good coverage.

The force_index_strategy_test.go file effectively tests both the computation and report generation aspects of the ForceIndexStrategy. It follows good testing practices such as using external test data, proper error handling, and cleanup of resources.

To further enhance the test suite:

  1. Consider adding edge cases or boundary conditions to ensure the strategy behaves correctly in all scenarios.
  2. If not already present in other files, consider adding integration tests that use the ForceIndexStrategy in combination with other components of the system.
  3. Ensure that these tests are included in any continuous integration pipelines to maintain the reliability of the ForceIndexStrategy as the project evolves.
README.md (1)

142-142: Replace hard tab with spaces for consistency.

The static analysis tool detected a hard tab on this line. To maintain consistency with the rest of the document, please replace the hard tab with spaces.

Apply this change:

--	[Force Index Strategy](strategy/volume/README.md#type-forceindexstrategy)
+-   [Force Index Strategy](strategy/volume/README.md#type-forceindexstrategy)
🧰 Tools
🪛 Markdownlint

142-142: Column: 2
Hard tabs

(MD010, no-hard-tabs)

strategy/volume/README.md (1)

144-200: LGTM! Consider adding a brief explanation of the Force Index indicator.

The new ForceIndexStrategy section is well-structured and consistent with the documentation of other strategies. The description of the strategy and its methods is accurate and complete.

To further improve the documentation, consider adding a brief explanation of what the Force Index indicator represents and how it's calculated. This would provide more context for users unfamiliar with this particular indicator.

strategy/volume/force_index_strategy.go (2)

39-39: Clarify the period calculation in the Name method

In the Name method, adding 1 to f.ForceIndex.IdlePeriod() may cause confusion about the actual period used. Review this calculation to ensure it accurately reflects the intended strategy period or adjust the formatting for clarity.


18-21: Add documentation for the ForceIndex field

Currently, the ForceIndex field in the ForceIndexStrategy struct lacks a descriptive comment. Adding documentation will improve code readability and maintainability.

Apply this diff to add the field comment:

 type ForceIndexStrategy struct {
+	// ForceIndex computes the Force Index indicator used in the strategy.
 	ForceIndex *volume.Fi[float64]
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 467323d and 1f3c361.

⛔ Files ignored due to path filters (1)
  • strategy/volume/testdata/force_index_strategy.csv is excluded by !**/*.csv
📒 Files selected for processing (5)
  • README.md (1 hunks)
  • strategy/volume/README.md (2 hunks)
  • strategy/volume/force_index_strategy.go (1 hunks)
  • strategy/volume/force_index_strategy_test.go (1 hunks)
  • strategy/volume/volume.go (1 hunks)
🧰 Additional context used
🪛 Markdownlint
README.md

142-142: Column: 2
Hard tabs

(MD010, no-hard-tabs)

🔇 Additional comments (7)
strategy/volume/volume.go (1)

29-29: LGTM: Force Index Strategy successfully added

The addition of NewForceIndexStrategy() to the AllStrategies() function is correct and aligns with the PR objectives. This change successfully introduces the Force Index Strategy to the available volume strategies.

strategy/volume/force_index_strategy_test.go (1)

7-15: LGTM: Import statements are appropriate and well-organized.

The import statements are correctly grouped and include all necessary packages for the test file's functionality.

README.md (2)

142-142: LGTM: Force Index Strategy added successfully.

The addition of the Force Index Strategy to the Volume Strategies section is consistent with the PR objectives and enhances the documentation. The link format and placement are correct.

🧰 Tools
🪛 Markdownlint

142-142: Column: 2
Hard tabs

(MD010, no-hard-tabs)


Line range hint 1-324: LGTM: Comprehensive update to README.md

The README.md file has been significantly improved to reflect the enhancements in version 2 of the Indicator Go module. The structure is well-organized, and the content is comprehensive, covering all major aspects of the module including:

  1. Lists of indicators and strategies
  2. New sections on repositories and backtesting
  3. Installation and usage instructions
  4. Licensing information

These updates align well with the PR objectives and the AI-generated summary.

🧰 Tools
🪛 Markdownlint

140-140: Column: 2
Hard tabs

(MD010, no-hard-tabs)


141-141: Column: 2
Hard tabs

(MD010, no-hard-tabs)


142-142: Column: 2
Hard tabs

(MD010, no-hard-tabs)


143-143: Column: 2
Hard tabs

(MD010, no-hard-tabs)


144-144: Column: 2
Hard tabs

(MD010, no-hard-tabs)


145-145: Column: 2
Hard tabs

(MD010, no-hard-tabs)

strategy/volume/README.md (2)

35-40: LGTM! ForceIndexStrategy is well-integrated into the index.

The ForceIndexStrategy has been correctly added to the index section, maintaining consistency with other strategy entries. The alphabetical order of strategies in the index has been preserved, which aids in easy navigation of the documentation.


Line range hint 1-200: Overall, the changes effectively introduce the ForceIndexStrategy.

The addition of the ForceIndexStrategy to the volume package documentation is well-executed. The new strategy is properly documented and integrated into the existing structure of the README. These changes align with the PR objectives of introducing the Force Index Strategy.

The documentation remains consistent and well-structured, maintaining the high quality of the existing content. This update enhances the comprehensiveness of the volume strategies documentation, providing users with information about another useful trading strategy.

strategy/volume/force_index_strategy.go (1)

64-64: Verify correct alignment after shifting actions by IdlePeriod

Shifting the actions by f.ForceIndex.IdlePeriod() adjusts for the initial period without sufficient data. Verify that this shift correctly aligns the actions with the corresponding snapshots to ensure accurate strategy recommendations.

Run the following script to confirm alignment:

Comment on lines +42 to +67
// Compute processes the provided asset snapshots and generates a stream of actionable recommendations.
func (f *ForceIndexStrategy) Compute(snapshots <-chan *asset.Snapshot) <-chan strategy.Action {
snapshotsSplice := helper.Duplicate(snapshots, 2)

closings := asset.SnapshotsAsClosings(snapshotsSplice[0])
volumes := asset.SnapshotsAsVolumes(snapshotsSplice[1])

fis := f.ForceIndex.Compute(closings, volumes)

actions := helper.Map(fis, func(fi float64) strategy.Action {
if fi > 0 {
return strategy.Buy
}

if fi < 0 {
return strategy.Sell
}

return strategy.Hold
})

// Force Index starts only after a full period.
actions = helper.Shift(actions, f.ForceIndex.IdlePeriod(), strategy.Hold)

return actions
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add error handling for potential channel issues in Compute

In the Compute method, there is no error handling for potential issues with the snapshots channel, such as premature closure or receiving nil values. Consider implementing error checks to handle such cases gracefully and prevent runtime panics.

Comment on lines +70 to +110
func (f *ForceIndexStrategy) Report(c <-chan *asset.Snapshot) *helper.Report {
//
// snapshots[0] -> dates
// snapshots[1] -> closings[0] -> closings
// closings[1] -> force index
// snapshots[2] -> volumes
// snapshots[3] -> actions -> annotations
// -> outcomes
//
snapshots := helper.Duplicate(c, 4)

dates := helper.Skip(asset.SnapshotsAsDates(snapshots[0]), f.ForceIndex.IdlePeriod())

closingsSplice := helper.Duplicate(
asset.SnapshotsAsClosings(snapshots[1]),
2,
)
volumes := asset.SnapshotsAsVolumes(snapshots[2])

fis := f.ForceIndex.Compute(closingsSplice[0], volumes)

closingsSplice[1] = helper.Skip(closingsSplice[1], f.ForceIndex.IdlePeriod())

actions, outcomes := strategy.ComputeWithOutcome(f, snapshots[3])
actions = helper.Skip(actions, f.ForceIndex.IdlePeriod())
outcomes = helper.Skip(outcomes, f.ForceIndex.IdlePeriod())

annotations := strategy.ActionsToAnnotations(actions)
outcomes = helper.MultiplyBy(outcomes, 100)

report := helper.NewReport(f.Name(), dates)
report.AddChart()
report.AddChart()

report.AddColumn(helper.NewNumericReportColumn("Close", closingsSplice[1]))
report.AddColumn(helper.NewNumericReportColumn("Force Index", fis), 1)
report.AddColumn(helper.NewAnnotationReportColumn(annotations), 0, 1)

report.AddColumn(helper.NewNumericReportColumn("Outcome", outcomes), 2)

return report
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Refactor the Report method for improved readability

The Report method contains multiple duplications and skips, which might affect readability and maintainability. Consider refactoring to simplify the data flow, possibly by extracting common patterns into helper functions or restructuring the method for clarity.

Comment on lines +23 to +28
// NewForceIndexStrategy function initializes a new Force Index strategy instance with the default parameters.
func NewForceIndexStrategy() *ForceIndexStrategy {
return NewForceIndexStrategyWith(
volume.DefaultFiPeriod,
)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add input validation for period parameter in NewForceIndexStrategyWith

The constructor NewForceIndexStrategyWith allows custom period specification but does not validate the input parameter. Consider adding validation to ensure that the period is a positive integer greater than zero to prevent potential runtime errors.

Apply this diff to add input validation:

 func NewForceIndexStrategyWith(period int) *ForceIndexStrategy {
+	if period <= 0 {
+		panic("period must be a positive integer greater than zero")
+	}
 	return &ForceIndexStrategy{
 		ForceIndex: volume.NewFiWithPeriod[float64](period),
 	}
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// NewForceIndexStrategy function initializes a new Force Index strategy instance with the default parameters.
func NewForceIndexStrategy() *ForceIndexStrategy {
return NewForceIndexStrategyWith(
volume.DefaultFiPeriod,
)
}
// NewForceIndexStrategy function initializes a new Force Index strategy instance with the default parameters.
func NewForceIndexStrategy() *ForceIndexStrategy {
return NewForceIndexStrategyWith(
volume.DefaultFiPeriod,
)
}
func NewForceIndexStrategyWith(period int) *ForceIndexStrategy {
if period <= 0 {
panic("period must be a positive integer greater than zero")
}
return &ForceIndexStrategy{
ForceIndex: volume.NewFiWithPeriod[float64](period),
}
}

@cinar cinar merged commit 0ea963f into master Oct 18, 2024
6 checks passed
@cinar cinar deleted the force-index-strategy branch October 18, 2024 01:07
@github-actions github-actions bot locked and limited conversation to collaborators Oct 18, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants