Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
5bbc6a0111
commit
a9f30f0fa4
@ -21,6 +21,7 @@ struct ContentView: View {
|
|||||||
@AppStorage("mt_enable_auto_refresh") private var storedEnableAutoRefresh = false
|
@AppStorage("mt_enable_auto_refresh") private var storedEnableAutoRefresh = false
|
||||||
@AppStorage("mt_refresh_sec") private var storedRefreshSeconds = 60
|
@AppStorage("mt_refresh_sec") private var storedRefreshSeconds = 60
|
||||||
@State private var showSetupSheet = false
|
@State private var showSetupSheet = false
|
||||||
|
@State private var showHelpSheet = false
|
||||||
@State private var setupDraft = UserSetupPreferences.default
|
@State private var setupDraft = UserSetupPreferences.default
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
@State private var showDebugPanel = false
|
@State private var showDebugPanel = false
|
||||||
@ -54,6 +55,9 @@ struct ContentView: View {
|
|||||||
.onDisappear { host.stop() }
|
.onDisappear { host.stop() }
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItemGroup(placement: .primaryAction) {
|
ToolbarItemGroup(placement: .primaryAction) {
|
||||||
|
Button("Help") {
|
||||||
|
showHelpSheet = true
|
||||||
|
}
|
||||||
Button("Setup") {
|
Button("Setup") {
|
||||||
syncStateFromSharedSettingsFileIfAvailable()
|
syncStateFromSharedSettingsFileIfAvailable()
|
||||||
setupDraft = storedWebPreferences.normalized().setupDefaults
|
setupDraft = storedWebPreferences.normalized().setupDefaults
|
||||||
@ -74,6 +78,9 @@ struct ContentView: View {
|
|||||||
.sheet(isPresented: $showSetupSheet) {
|
.sheet(isPresented: $showSetupSheet) {
|
||||||
setupSheet
|
setupSheet
|
||||||
}
|
}
|
||||||
|
.sheet(isPresented: $showHelpSheet) {
|
||||||
|
HelpSheetView()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var sharedSettingsURL: URL {
|
private var sharedSettingsURL: URL {
|
||||||
@ -330,6 +337,64 @@ struct ContentView: View {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private struct HelpSheetView: View {
|
||||||
|
@Environment(\.dismiss) private var dismiss
|
||||||
|
|
||||||
|
private var helpFileURL: URL? {
|
||||||
|
let fm = FileManager.default
|
||||||
|
let candidates = [
|
||||||
|
Bundle.main.url(forResource: "help", withExtension: "html", subdirectory: "Help"),
|
||||||
|
Bundle.main.url(forResource: "help", withExtension: "html"),
|
||||||
|
Bundle.main.resourceURL?.appendingPathComponent("Help/help.html"),
|
||||||
|
Bundle.main.resourceURL?.appendingPathComponent("help.html"),
|
||||||
|
].compactMap { $0 }
|
||||||
|
return candidates.first(where: { fm.fileExists(atPath: $0.path) })
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
NavigationStack {
|
||||||
|
Group {
|
||||||
|
if let helpFileURL {
|
||||||
|
HelpDocumentWebView(fileURL: helpFileURL)
|
||||||
|
} else {
|
||||||
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
|
Text("Help file not found.")
|
||||||
|
.font(.title3.weight(.semibold))
|
||||||
|
Text("Expected bundled file: help.html")
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
|
||||||
|
.padding(24)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.navigationTitle("Help & Quick Start")
|
||||||
|
.toolbar {
|
||||||
|
ToolbarItem(placement: .confirmationAction) {
|
||||||
|
Button("Done") { dismiss() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.frame(minWidth: 860, minHeight: 640)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct HelpDocumentWebView: NSViewRepresentable {
|
||||||
|
let fileURL: URL
|
||||||
|
|
||||||
|
func makeNSView(context: Context) -> WKWebView {
|
||||||
|
let webView = WKWebView(frame: .zero)
|
||||||
|
webView.allowsBackForwardNavigationGestures = true
|
||||||
|
webView.loadFileURL(fileURL, allowingReadAccessTo: fileURL.deletingLastPathComponent())
|
||||||
|
return webView
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateNSView(_ webView: WKWebView, context: Context) {
|
||||||
|
if webView.url != fileURL {
|
||||||
|
webView.loadFileURL(fileURL, allowingReadAccessTo: fileURL.deletingLastPathComponent())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
ContentView()
|
ContentView()
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
196
mac/src/App/Help/help.html
Normal file
196
mac/src/App/Help/help.html
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>Help & Quick Start</title>
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
color-scheme: light dark;
|
||||||
|
--bg: #0e1117;
|
||||||
|
--panel: #131925;
|
||||||
|
--text: #f3f6fb;
|
||||||
|
--muted: #a6b3c7;
|
||||||
|
--accent: #4db2ff;
|
||||||
|
--ok: #4bd37b;
|
||||||
|
--warn: #ff9f43;
|
||||||
|
--line: #2a3346;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
:root {
|
||||||
|
--bg: #f6f8fc;
|
||||||
|
--panel: #ffffff;
|
||||||
|
--text: #172033;
|
||||||
|
--muted: #5b6980;
|
||||||
|
--accent: #006fde;
|
||||||
|
--ok: #12834a;
|
||||||
|
--warn: #b85b00;
|
||||||
|
--line: #d7deea;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||||
|
color: var(--text);
|
||||||
|
background: radial-gradient(circle at top right, rgba(77, 178, 255, 0.18), transparent 40%), var(--bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
max-width: 980px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 28px 24px 56px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 0 0 8px;
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
margin: 0 0 20px;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
background: color-mix(in oklab, var(--panel) 92%, transparent);
|
||||||
|
border-radius: 14px;
|
||||||
|
padding: 16px 18px;
|
||||||
|
margin: 0 0 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin: 0 0 10px;
|
||||||
|
font-size: 1.05rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 12px 0 8px;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p,
|
||||||
|
li {
|
||||||
|
line-height: 1.45;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: color-mix(in oklab, var(--panel) 80%, var(--line));
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 1px 6px;
|
||||||
|
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag {
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
border-radius: 999px;
|
||||||
|
padding: 2px 10px;
|
||||||
|
margin-right: 6px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ok {
|
||||||
|
color: var(--ok);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warn {
|
||||||
|
color: var(--warn);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
<h1>Help & Quick Start</h1>
|
||||||
|
<p class="subtitle">A quick guide to reading signals, choosing settings, and troubleshooting.</p>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Start in 60 Seconds</h2>
|
||||||
|
<ol>
|
||||||
|
<li>Set a symbol like <code>AAPL</code> or <code>BTC-USD</code>.</li>
|
||||||
|
<li>Choose <code>Timeframe</code> (<code>1d</code> is a good default) and <code>Period</code> (<code>6mo</code>).</li>
|
||||||
|
<li>Keep <code>Ignore potentially live last bar</code> enabled.</li>
|
||||||
|
<li>Review trend status and chart markers.</li>
|
||||||
|
<li>Use Export to download CSV/PDF outputs.</li>
|
||||||
|
</ol>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Signal Rules</h2>
|
||||||
|
<p>
|
||||||
|
<span class="tag"><span class="ok">real_bull</span> close above previous high</span>
|
||||||
|
<span class="tag"><span class="warn">real_bear</span> close below previous low</span>
|
||||||
|
<span class="tag">fake close inside previous range</span>
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>Trend starts after <strong>2 consecutive real bars</strong> in the same direction.</li>
|
||||||
|
<li>Trend reverses only after <strong>2 consecutive opposite real bars</strong>.</li>
|
||||||
|
<li>Fake bars are noise and do not reverse trend.</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Data Settings</h2>
|
||||||
|
<h3>Core fields</h3>
|
||||||
|
<ul>
|
||||||
|
<li><code>Symbol</code>: ticker or pair, e.g. <code>AAPL</code>, <code>MSFT</code>, <code>BTC-USD</code>.</li>
|
||||||
|
<li><code>Timeframe</code>: candle size. Start with <code>1d</code> for cleaner swings.</li>
|
||||||
|
<li><code>Period</code>: amount of history to load. Start with <code>6mo</code>.</li>
|
||||||
|
<li><code>Max bars</code>: limits loaded candles for speed and chart readability.</li>
|
||||||
|
</ul>
|
||||||
|
<h3>Optional filters</h3>
|
||||||
|
<ul>
|
||||||
|
<li><code>Use previous body range</code>: ignores wick-only breakouts.</li>
|
||||||
|
<li><code>Enable volume filter</code>: treats low-volume bars as fake.</li>
|
||||||
|
<li><code>Hide market-closed gaps</code>: recommended ON for stocks.</li>
|
||||||
|
<li><code>Enable auto-refresh</code>: useful for live monitoring only.</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Chart Reading</h2>
|
||||||
|
<ul>
|
||||||
|
<li>Green triangle-up markers show <code>real_bull</code> bars.</li>
|
||||||
|
<li>Red triangle-down markers show <code>real_bear</code> bars.</li>
|
||||||
|
<li>Gray candles (if enabled) de-emphasize fake/noise bars.</li>
|
||||||
|
<li>Volume bars are color-coded by trend state.</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Troubleshooting</h2>
|
||||||
|
<ul>
|
||||||
|
<li>If no data appears, verify ticker format (for example <code>BTC-USD</code>, not <code>BTCUSD</code>).</li>
|
||||||
|
<li>If results look noisy, switch to <code>1d</code> and reduce optional filters.</li>
|
||||||
|
<li>If trend seems delayed, remember trend transitions require two real bars.</li>
|
||||||
|
<li>This tool is analysis-only and does not place trades.</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -30,17 +30,17 @@
|
|||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||||
EAB6606E2F3FD5C000ED41BA /* ManeshTraderMac */ = {
|
EAB6606E2F3FD5C000ED41BA /* App */ = {
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
path = App;
|
path = App;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
EAB6607C2F3FD5C100ED41BA /* ManeshTraderMacTests */ = {
|
EAB6607C2F3FD5C100ED41BA /* AppTests */ = {
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
path = AppTests;
|
path = AppTests;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
EAB660862F3FD5C100ED41BA /* ManeshTraderMacUITests */ = {
|
EAB660862F3FD5C100ED41BA /* AppUITests */ = {
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
path = AppUITests;
|
path = AppUITests;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -75,9 +75,9 @@
|
|||||||
EAB660632F3FD5C000ED41BA = {
|
EAB660632F3FD5C000ED41BA = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
EAB6606E2F3FD5C000ED41BA /* ManeshTraderMac */,
|
EAB6606E2F3FD5C000ED41BA /* App */,
|
||||||
EAB6607C2F3FD5C100ED41BA /* ManeshTraderMacTests */,
|
EAB6607C2F3FD5C100ED41BA /* AppTests */,
|
||||||
EAB660862F3FD5C100ED41BA /* ManeshTraderMacUITests */,
|
EAB660862F3FD5C100ED41BA /* AppUITests */,
|
||||||
EAB6606D2F3FD5C000ED41BA /* Products */,
|
EAB6606D2F3FD5C000ED41BA /* Products */,
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -108,7 +108,7 @@
|
|||||||
dependencies = (
|
dependencies = (
|
||||||
);
|
);
|
||||||
fileSystemSynchronizedGroups = (
|
fileSystemSynchronizedGroups = (
|
||||||
EAB6606E2F3FD5C000ED41BA /* ManeshTraderMac */,
|
EAB6606E2F3FD5C000ED41BA /* App */,
|
||||||
);
|
);
|
||||||
name = ManeshTraderMac;
|
name = ManeshTraderMac;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
@ -131,7 +131,7 @@
|
|||||||
EAB6607B2F3FD5C100ED41BA /* PBXTargetDependency */,
|
EAB6607B2F3FD5C100ED41BA /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
fileSystemSynchronizedGroups = (
|
fileSystemSynchronizedGroups = (
|
||||||
EAB6607C2F3FD5C100ED41BA /* ManeshTraderMacTests */,
|
EAB6607C2F3FD5C100ED41BA /* AppTests */,
|
||||||
);
|
);
|
||||||
name = ManeshTraderMacTests;
|
name = ManeshTraderMacTests;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
@ -154,7 +154,7 @@
|
|||||||
EAB660852F3FD5C100ED41BA /* PBXTargetDependency */,
|
EAB660852F3FD5C100ED41BA /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
fileSystemSynchronizedGroups = (
|
fileSystemSynchronizedGroups = (
|
||||||
EAB660862F3FD5C100ED41BA /* ManeshTraderMacUITests */,
|
EAB660862F3FD5C100ED41BA /* AppUITests */,
|
||||||
);
|
);
|
||||||
name = ManeshTraderMacUITests;
|
name = ManeshTraderMacUITests;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
@ -186,7 +186,7 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = EAB660672F3FD5C000ED41BA /* Build configuration list for PBXProject "ManeshTraderMac" */;
|
buildConfigurationList = EAB660672F3FD5C000ED41BA /* Build configuration list for PBXProject "MacShell" */;
|
||||||
developmentRegion = en;
|
developmentRegion = en;
|
||||||
hasScannedForEncodings = 0;
|
hasScannedForEncodings = 0;
|
||||||
knownRegions = (
|
knownRegions = (
|
||||||
@ -540,7 +540,7 @@
|
|||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
EAB660672F3FD5C000ED41BA /* Build configuration list for PBXProject "ManeshTraderMac" */ = {
|
EAB660672F3FD5C000ED41BA /* Build configuration list for PBXProject "MacShell" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
EAB6608B2F3FD5C100ED41BA /* Debug */,
|
EAB6608B2F3FD5C100ED41BA /* Debug */,
|
||||||
|
|||||||
@ -6,6 +6,7 @@ Native macOS shell around the web app in `web/src/`.
|
|||||||
- Starts/stops bundled backend executable from app resources
|
- Starts/stops bundled backend executable from app resources
|
||||||
- Hosts UI in `WKWebView` at local `127.0.0.1` URL
|
- Hosts UI in `WKWebView` at local `127.0.0.1` URL
|
||||||
- Keeps user inside app window (no external browser)
|
- Keeps user inside app window (no external browser)
|
||||||
|
- Provides a native toolbar `Help` button that opens bundled quick-start docs in-app
|
||||||
|
|
||||||
## Build Self-Contained App
|
## Build Self-Contained App
|
||||||
From repo root:
|
From repo root:
|
||||||
|
|||||||
@ -155,6 +155,19 @@ def save_web_settings(settings: dict[str, Any]) -> None:
|
|||||||
SETTINGS_PATH.write_text(json.dumps(normalize_web_settings(settings), indent=2), encoding="utf-8")
|
SETTINGS_PATH.write_text(json.dumps(normalize_web_settings(settings), indent=2), encoding="utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
@st.cache_data(show_spinner=False)
|
||||||
|
def load_help_markdown() -> str:
|
||||||
|
onboarding_path = Path(__file__).with_name("ONBOARDING.md")
|
||||||
|
if onboarding_path.exists():
|
||||||
|
return onboarding_path.read_text(encoding="utf-8")
|
||||||
|
return "Help content not found."
|
||||||
|
|
||||||
|
|
||||||
|
@st.dialog("Help & Quick Start", width="large")
|
||||||
|
def help_dialog() -> None:
|
||||||
|
st.markdown(load_help_markdown())
|
||||||
|
|
||||||
|
|
||||||
@st.cache_data(show_spinner=False, ttl=3600)
|
@st.cache_data(show_spinner=False, ttl=3600)
|
||||||
def lookup_symbol_candidates(query: str, max_results: int = 10) -> list[dict[str, str]]:
|
def lookup_symbol_candidates(query: str, max_results: int = 10) -> list[dict[str, str]]:
|
||||||
cleaned = query.strip()
|
cleaned = query.strip()
|
||||||
@ -226,51 +239,19 @@ def resolve_symbol_identity(symbol: str) -> dict[str, str]:
|
|||||||
return {"symbol": normalized_symbol, "name": "", "exchange": ""}
|
return {"symbol": normalized_symbol, "name": "", "exchange": ""}
|
||||||
|
|
||||||
|
|
||||||
@st.cache_data(show_spinner=False)
|
|
||||||
def load_onboarding_markdown() -> str:
|
|
||||||
onboarding_path = Path(__file__).with_name("ONBOARDING.md")
|
|
||||||
if onboarding_path.exists():
|
|
||||||
return onboarding_path.read_text(encoding="utf-8")
|
|
||||||
return "ONBOARDING.md not found in project root."
|
|
||||||
|
|
||||||
|
|
||||||
@st.dialog("Onboarding Guide", width="large")
|
|
||||||
def onboarding_dialog() -> None:
|
|
||||||
st.markdown(load_onboarding_markdown())
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
st.set_page_config(page_title="Real Bars vs Fake Bars Analyzer", layout="wide")
|
st.set_page_config(page_title="Real Bars vs Fake Bars Analyzer", layout="wide")
|
||||||
st.title("Real Bars vs Fake Bars Trend Analyzer")
|
st.title("Real Bars vs Fake Bars Trend Analyzer")
|
||||||
st.caption(
|
st.caption(
|
||||||
"Price-action tool that classifies closed bars, filters fake bars, and tracks trend persistence using only real bars."
|
"Price-action tool that classifies closed bars, filters fake bars, and tracks trend persistence using only real bars."
|
||||||
)
|
)
|
||||||
if st.button("Open ONBOARDING.md", type="tertiary"):
|
|
||||||
onboarding_dialog()
|
|
||||||
|
|
||||||
with st.expander("Help / Quick Start", expanded=False):
|
|
||||||
st.markdown(
|
|
||||||
"""
|
|
||||||
**Start in 60 seconds**
|
|
||||||
1. Set a symbol like `AAPL` or `BTC-USD`.
|
|
||||||
2. Choose `Timeframe` (`1d` is a good default) and `Period` (`6mo`).
|
|
||||||
3. Keep **Ignore potentially live last bar** enabled.
|
|
||||||
4. Review trend status and markers:
|
|
||||||
- Green triangle: `real_bull`
|
|
||||||
- Red triangle: `real_bear`
|
|
||||||
- `fake` bars are noise and ignored by trend logic
|
|
||||||
5. Use **Export** to download CSV/PDF outputs.
|
|
||||||
|
|
||||||
**Rule summary**
|
|
||||||
- `real_bull`: close > previous high
|
|
||||||
- `real_bear`: close < previous low
|
|
||||||
- `fake`: close inside previous range
|
|
||||||
- Trend starts/reverses only after 2 consecutive real bars in that direction.
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
with st.sidebar:
|
with st.sidebar:
|
||||||
st.header("Data Settings")
|
st.header("Data Settings")
|
||||||
|
if st.button("Help / Quick Start", use_container_width=True):
|
||||||
|
help_dialog()
|
||||||
|
st.divider()
|
||||||
|
|
||||||
query_params = st.query_params
|
query_params = st.query_params
|
||||||
persisted_settings = load_web_settings()
|
persisted_settings = load_web_settings()
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user