@363045841yyt/klinechart 0.6.3 → 0.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +5 -5
- package/dist/index.js +1672 -1152
- package/dist/klinechart.css +1 -1
- package/dist/src/config/chartSettings.d.ts +11 -1
- package/dist/src/core/indicators/calculators.d.ts +140 -0
- package/dist/src/core/indicators/macdState.d.ts +58 -0
- package/dist/src/core/indicators/scheduler.d.ts +12 -0
- package/dist/src/core/indicators/soa.d.ts +115 -0
- package/dist/src/core/renderers/Indicator/macd.d.ts +3 -11
- package/dist/src/core/renderers/Indicator/rsi.d.ts +10 -0
- package/dist/src/core/renderers/webgl/candleSurface.d.ts +3 -0
- package/package.json +1 -1
package/dist/klinechart.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
.kline-tooltip[data-v-d0fe85e6]{z-index:10;color:#000000c7;pointer-events:none;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);background:#ffffffeb;border:1px solid #0000001f;border-radius:8px;min-width:200px;max-width:260px;padding:10px 12px;font-size:12px;line-height:1.4;position:absolute;box-shadow:0 6px 18px #0000001f}.kline-tooltip__title[data-v-d0fe85e6]{justify-content:space-between;gap:10px;margin-bottom:6px;font-weight:600;display:flex}.kline-tooltip__grid[data-v-d0fe85e6]{grid-template-columns:1fr;gap:2px;display:grid}.kline-tooltip__grid .row[data-v-d0fe85e6]{justify-content:space-between;gap:10px;display:flex}.kline-tooltip__grid .row span[data-v-d0fe85e6]:first-child{color:#0000008f}@supports (anchor-name:--kmap-anchor) and (position-anchor:--kmap-anchor){.kline-tooltip.use-anchor[data-v-d0fe85e6]{position-anchor:--kline-tooltip-anchor;left:anchor(left);top:anchor(top);position:absolute}.kline-tooltip.use-anchor.anchor-right-bottom[data-v-d0fe85e6]{transform:translate(14px,14px)}.kline-tooltip.use-anchor.anchor-left-bottom[data-v-d0fe85e6]{transform:translate(calc(-100% - 14px),14px)}}.marker-tooltip[data-v-5574cc25]{z-index:10;color:#000000c7;pointer-events:none;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);background:#ffffffeb;border:1px solid #0000001f;border-radius:8px;min-width:180px;max-width:260px;padding:10px 12px;font-size:12px;line-height:1.4;position:absolute;box-shadow:0 6px 18px #0000001f}.marker-tooltip__title[data-v-5574cc25]{justify-content:space-between;gap:10px;margin-bottom:6px;font-weight:600;display:flex}.marker-tooltip__content[data-v-5574cc25]{grid-template-columns:1fr;gap:2px;display:grid}.marker-tooltip__content .row[data-v-5574cc25]{justify-content:space-between;gap:10px;display:flex}.marker-tooltip__content .row span[data-v-5574cc25]:first-child{color:#0000008f}@supports (anchor-name:--kmap-anchor) and (position-anchor:--kmap-anchor){.marker-tooltip.use-anchor[data-v-5574cc25]{position-anchor:--marker-tooltip-anchor;left:anchor(left);top:anchor(top);position:absolute}.marker-tooltip.use-anchor.anchor-right-bottom[data-v-5574cc25]{transform:translate(12px,12px)}.marker-tooltip.use-anchor.anchor-left-bottom[data-v-5574cc25]{transform:translate(calc(-100% - 12px),12px)}}.params-overlay[data-v-bb1d1eb3]{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;background:#0000004d;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.indicator-params[data-v-bb1d1eb3]{background:#fff;border:1px solid #e0e0e0;border-radius:12px;width:90vw;min-width:340px;max-width:420px;overflow:hidden;box-shadow:0 8px 40px #00000026}.params-header[data-v-bb1d1eb3]{background:#f8f8f8;border-bottom:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:16px 20px;display:flex}.header-left[data-v-bb1d1eb3]{align-items:baseline;gap:8px;display:flex}.header-right[data-v-bb1d1eb3]{align-items:center;gap:8px;display:flex}.params-title[data-v-bb1d1eb3]{color:#1a1a1a;letter-spacing:.2px;font-size:14px;font-weight:600}.params-subtitle[data-v-bb1d1eb3]{color:#999;font-size:11px}.toggle-desc-btn[data-v-bb1d1eb3]{cursor:pointer;color:#888;background:#fff;border:1px solid #e0e0e0;border-radius:6px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;transition:all .2s;display:flex}.toggle-desc-btn[data-v-bb1d1eb3]:hover{color:#555;background:#f0f0f0;border-color:#ccc}.toggle-desc-btn.active[data-v-bb1d1eb3]{color:#fff;background:#1a1a1a;border-color:#1a1a1a}.toggle-desc-btn svg[data-v-bb1d1eb3]{width:14px;height:14px}.params-close[data-v-bb1d1eb3]{cursor:pointer;color:#888;background:#fff;border:1px solid #e0e0e0;border-radius:6px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;transition:background .15s,color .15s,border-color .15s;display:flex}.params-close[data-v-bb1d1eb3]:hover{color:#333;background:#f0f0f0;border-color:#ccc}.params-close svg[data-v-bb1d1eb3]{width:14px;height:14px}.indicator-description[data-v-bb1d1eb3]{background:#f0f7ff;border-bottom:1px solid #d6e8f5;padding:12px 20px}.indicator-description p[data-v-bb1d1eb3]{color:#2c5282;margin:0;font-size:12px;line-height:1.6}.params-body[data-v-bb1d1eb3]{flex-direction:column;gap:10px;padding:16px 20px;display:flex}.param-item[data-v-bb1d1eb3]{background:#f8f8f8;border:1px solid #e8e8e8;border-radius:8px;padding:10px 14px;transition:border-color .2s}.param-item[data-v-bb1d1eb3]:has(.param-input:focus){border-color:#bbb}.param-item.has-desc[data-v-bb1d1eb3]{padding:10px 14px 8px}.param-header[data-v-bb1d1eb3]{justify-content:space-between;align-items:center;gap:16px;display:flex}.param-label[data-v-bb1d1eb3]{flex-direction:column;gap:3px;display:flex}.param-label-text[data-v-bb1d1eb3]{color:#333;font-size:13px;font-weight:500}.param-range[data-v-bb1d1eb3]{color:#999;font-size:11px}.param-description[data-v-bb1d1eb3]{color:#666;border-top:1px dashed #e0e0e0;margin-top:8px;padding-top:8px;font-size:11px;line-height:1.5}.input-wrapper[data-v-bb1d1eb3]{background:#fff;border:1px solid #d0d0d0;border-radius:7px;align-items:stretch;height:32px;transition:border-color .2s;display:flex;overflow:hidden}.input-wrapper[data-v-bb1d1eb3]:focus-within{border-color:#999}.stepper-btn[data-v-bb1d1eb3]{cursor:pointer;color:#666;background:#f0f0f0;border:none;flex-shrink:0;justify-content:center;align-items:center;width:28px;font-size:15px;font-weight:400;line-height:1;transition:background .15s,color .15s;display:flex}.stepper-btn[data-v-bb1d1eb3]:hover:not(:disabled){color:#333;background:#e0e0e0}.stepper-btn[data-v-bb1d1eb3]:disabled{color:#ccc;cursor:not-allowed}.param-input[data-v-bb1d1eb3]{text-align:center;color:#1a1a1a;appearance:textfield;background:0 0;border:none;border-left:1px solid #e8e8e8;border-right:1px solid #e8e8e8;width:60px;font-size:13px;font-weight:600}.param-input[data-v-bb1d1eb3]::-webkit-inner-spin-button{-webkit-appearance:none}.param-input[data-v-bb1d1eb3]::-webkit-outer-spin-button{-webkit-appearance:none}.param-input[data-v-bb1d1eb3]:focus{outline:none}.params-footer[data-v-bb1d1eb3]{background:#f8f8f8;border-top:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:12px 20px;display:flex}.footer-right[data-v-bb1d1eb3]{gap:8px;display:flex}.params-btn[data-v-bb1d1eb3]{cursor:pointer;border:1px solid #0000;border-radius:7px;align-items:center;gap:5px;padding:6px 14px;font-size:13px;font-weight:500;line-height:1.4;transition:all .15s;display:flex}.params-btn svg[data-v-bb1d1eb3]{flex-shrink:0;width:12px;height:12px}.params-btn.reset[data-v-bb1d1eb3]{color:#666;background:0 0;border-color:#d0d0d0}.params-btn.reset[data-v-bb1d1eb3]:hover{color:#e74c3c;background:#e74c3c14;border-color:#c0392b}.params-btn.cancel[data-v-bb1d1eb3]{color:#666;background:0 0;border-color:#d0d0d0}.params-btn.cancel[data-v-bb1d1eb3]:hover{color:#333;background:#f0f0f0;border-color:#bbb}.params-btn.confirm[data-v-bb1d1eb3]{color:#fff;background:#1a1a1a;border-color:#1a1a1a}.params-btn.confirm[data-v-bb1d1eb3]:hover{background:#333;border-color:#333;transform:translateY(-1px);box-shadow:0 2px 10px #00000026}.params-btn.confirm[data-v-bb1d1eb3]:active{box-shadow:none;transform:translateY(0)}.overlay-enter-active[data-v-bb1d1eb3],.overlay-leave-active[data-v-bb1d1eb3]{transition:opacity .2s}.overlay-enter-from[data-v-bb1d1eb3],.overlay-leave-to[data-v-bb1d1eb3]{opacity:0}.modal-enter-active[data-v-bb1d1eb3]{transition:all .22s cubic-bezier(.34,1.56,.64,1)}.modal-leave-active[data-v-bb1d1eb3]{transition:all .16s ease-in}.modal-enter-from[data-v-bb1d1eb3]{opacity:0;transform:scale(.88)translateY(-16px)}.modal-leave-to[data-v-bb1d1eb3]{opacity:0;transform:scale(.94)translateY(8px)}.slide-enter-active[data-v-bb1d1eb3],.slide-leave-active[data-v-bb1d1eb3]{transition:all .2s;overflow:hidden}.slide-enter-from[data-v-bb1d1eb3],.slide-leave-to[data-v-bb1d1eb3]{opacity:0;max-height:0;margin-top:0;padding-top:0;padding-bottom:0}.indicator-selector[data-v-f3fbebbd]{width:80%;margin:20px;position:relative}.indicator-scroll-container[data-v-f3fbebbd]{scrollbar-width:none;-webkit-overflow-scrolling:touch;text-align:center;width:100%;overflow:auto hidden}.indicator-scroll-container[data-v-f3fbebbd]::-webkit-scrollbar{display:none}.indicator-list[data-v-f3fbebbd]{gap:8px;margin:0 auto;padding:2px;display:inline-flex}.indicator-divider[data-v-f3fbebbd]{background:#d9d9d9;align-self:center;width:1px;height:20px}.indicator-item[data-v-f3fbebbd]{align-items:center;gap:4px;display:flex}.indicator-item.draggable[data-v-f3fbebbd],.indicator-item.draggable .indicator-btn[data-v-f3fbebbd],.indicator-item.draggable[data-v-f3fbebbd]:hover,.indicator-item.draggable:hover .indicator-btn[data-v-f3fbebbd]{cursor:move}.indicator-item.is-dragging[data-v-f3fbebbd]{opacity:.6}.indicator-item.drag-over .indicator-btn[data-v-f3fbebbd]{border-color:#1a1a1a;box-shadow:0 0 0 2px #1a1a1a1f}.indicator-btn-wrapper[data-v-f3fbebbd]{position:relative}.indicator-btn[data-v-f3fbebbd]{color:#666;cursor:pointer;white-space:nowrap;background:#fff;border:1px solid #e0e0e0;border-radius:16px;flex-shrink:0;justify-content:center;align-items:center;gap:4px;padding:6px 16px;font-size:13px;font-weight:500;transition:all .3s;display:flex;position:relative;overflow:hidden}.indicator-btn[data-v-f3fbebbd]:hover:not(.hovering){color:#333;background:#f8f8f8;border-color:#ccc}.indicator-btn.active[data-v-f3fbebbd]{color:#1a1a1a;background:#f8f8f8;border-color:#1a1a1a}.indicator-btn.active[data-v-f3fbebbd]:hover:not(.hovering){background:#f0f0f0;border-color:#333}.btn-content[data-v-f3fbebbd]{z-index:1;position:relative}.param-hint[data-v-f3fbebbd]{opacity:.85;font-size:11px}.hover-overlay[data-v-f3fbebbd]{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:2;background:#ffffffd9;border-radius:16px;justify-content:center;align-items:center;gap:4px;display:flex;position:absolute;inset:0}.action-btn[data-v-f3fbebbd]{color:#666;cursor:pointer;background:0 0;border:none;border-radius:50%;justify-content:center;align-items:center;width:24px;height:24px;padding:0;transition:all .2s;display:flex}.action-btn[data-v-f3fbebbd]:hover{color:#333;background:#0000000f}.settings-btn[data-v-f3fbebbd]:hover{color:#1a1a1a}.remove-btn[data-v-f3fbebbd]:hover{color:#ff4d4f}.divider[data-v-f3fbebbd]{background:#e0e0e0;width:1px;height:14px}.add-btn[data-v-f3fbebbd]{anchor-name:--indicator-add-btn;color:#999;cursor:pointer;background:0 0;border:1px dashed #d9d9d9;border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;width:32px;height:32px;padding:0;transition:all .3s;display:flex}.add-btn[data-v-f3fbebbd]:hover{color:#1a1a1a;background:#1a1a1a0a;border-color:#1a1a1a}.add-menu[data-v-f3fbebbd]{white-space:nowrap;z-index:9999;background:#fff;border-radius:8px;padding:8px 0;position:fixed;transform:translate(-50%);box-shadow:0 6px 16px #00000014,0 3px 6px -4px #0000001f,0 9px 28px 8px #0000000d}@supports (anchor-name:--kmap-anchor) and (position-anchor:--kmap-anchor){.add-menu.use-anchor[data-v-f3fbebbd]{position-anchor:--indicator-add-btn;left:anchor(center);top:anchor(top);max-width:calc(100vw - 16px);position:fixed;transform:translate(-50%,calc(-100% - 8px))}}.menu-section[data-v-f3fbebbd]{padding:4px 0}.menu-section[data-v-f3fbebbd]:not(:last-child){border-bottom:1px solid #f0f0f0}.menu-title[data-v-f3fbebbd]{color:#999;padding:4px 16px;font-size:12px;font-weight:500}.menu-items[data-v-f3fbebbd]{flex-direction:column;gap:2px;display:flex}.menu-item[data-v-f3fbebbd]{text-align:left;color:#333;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;width:100%;padding:8px 16px;font-size:13px;transition:background .2s;display:flex}.menu-item[data-v-f3fbebbd]:hover:not(.disabled){background:#f5f5f5}.menu-item.disabled[data-v-f3fbebbd]{color:#999;cursor:not-allowed}.menu-item .param-hint[data-v-f3fbebbd]{color:#999;font-size:11px}.active-tag[data-v-f3fbebbd]{color:#1a1a1a;align-items:center;margin-left:auto;display:flex}.fade-enter-active[data-v-f3fbebbd],.fade-leave-active[data-v-f3fbebbd]{transition:opacity .2s}.fade-enter-from[data-v-f3fbebbd],.fade-leave-to[data-v-f3fbebbd]{opacity:0}.slide-enter-active[data-v-f3fbebbd],.slide-leave-active[data-v-f3fbebbd]{transition:all .2s}.slide-enter-from[data-v-f3fbebbd],.slide-leave-to[data-v-f3fbebbd]{opacity:0;transform:translate(-50%)translateY(8px)}.drawing-style-toolbar[data-v-92699cb2]{-webkit-backdrop-filter:blur(8px);z-index:100;-webkit-user-select:none;user-select:none;pointer-events:auto;background:#fafbfce0;border:1px solid #e5e7eb;border-radius:6px;align-items:center;gap:6px;height:32px;padding:4px 8px;display:flex;position:absolute;top:8px;left:50%;transform:translate(-50%);box-shadow:0 1px 3px #0000000f}.toolbar-item[data-v-92699cb2]{justify-content:center;align-items:center;display:inline-flex}.color-item[data-v-92699cb2]{width:24px;height:24px;position:relative}.color-swatch[data-v-92699cb2]{cursor:pointer;border:1px solid #d1d5db;border-radius:4px;width:100%;height:100%;display:block}.color-input[data-v-92699cb2]{opacity:0;cursor:pointer;width:100%;height:100%;position:absolute;inset:0}.toolbar-select[data-v-92699cb2]{color:#374151;cursor:pointer;background:#fff;border:1px solid #d1d5db;border-radius:4px;outline:none;height:24px;padding:0 4px;font-size:12px}.toolbar-select[data-v-92699cb2]:hover{border-color:#9ca3af}.toolbar-btn[data-v-92699cb2]{color:#6b7280;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:4px;justify-content:center;align-items:center;width:24px;height:24px;padding:0;transition:border-color .15s,background .15s,color .15s;display:inline-flex}.toolbar-btn[data-v-92699cb2]:hover{color:#374151;background:#f3f4f6;border-color:#d1d5db}.delete-btn[data-v-92699cb2]:hover{color:#dc2626;background:#fef2f2;border-color:#fca5a5}.delete-icon[data-v-92699cb2]{width:14px;height:14px}.left-toolbar[data-v-f47a57b0]{box-sizing:border-box;-webkit-user-select:none;user-select:none;background:#fafbfc;border:1px solid #e5e7eb;border-radius:6px;flex-direction:column;flex:0 0 40px;align-items:center;gap:6px;padding:8px 5px;display:flex;box-shadow:0 1px 3px #0000000f}.left-toolbar__group[data-v-f47a57b0]{flex-direction:column;gap:4px;display:flex}.left-toolbar__divider[data-v-f47a57b0]{background:#e5e7eb;width:18px;height:1px}.left-toolbar__button[data-v-f47a57b0]{color:#6b7280;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:4px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;transition:border-color .15s,background .15s,color .15s;display:inline-flex;position:relative}.left-toolbar__button[data-v-f47a57b0]:hover{color:#374151;background:#f3f4f6;border-color:#d1d5db}.left-toolbar__button.active[data-v-f47a57b0]{color:#1f2937;background:#e5e7eb;border-color:#9ca3af}.left-toolbar__button[data-v-f47a57b0]:focus-visible{border-color:#6b7280;outline:none}.tool-icon[data-v-f47a57b0]{width:16px;height:16px}.corner-indicator[data-v-f47a57b0]{cursor:pointer;width:8px;height:8px;position:absolute;bottom:0;right:0;overflow:hidden}.corner-indicator[data-v-f47a57b0]:after{content:"";opacity:.45;border-bottom:5px solid;border-left:5px solid #0000;width:0;height:0;transition:opacity .15s;position:absolute;bottom:0;right:0}.left-toolbar__button:hover .corner-indicator[data-v-f47a57b0]:after,.left-toolbar__button.active .corner-indicator[data-v-f47a57b0]:after{opacity:.7}.corner-indicator.open[data-v-f47a57b0]:after{opacity:.8}.tool-dropdown[data-v-f47a57b0]{-webkit-backdrop-filter:blur(8px);box-sizing:border-box;z-index:100;background:#fafbfcd1;border:1px solid #e5e7eb;border-radius:6px;flex-direction:row;align-items:center;gap:4px;height:40px;padding:0 5px;display:flex;position:absolute;top:50%;left:calc(100% + 13px);transform:translateY(-50%);box-shadow:0 1px 3px #0000000f}.tool-item[data-v-f47a57b0]{position:relative}.dropdown-enter-active[data-v-f47a57b0],.dropdown-leave-active[data-v-f47a57b0]{transition:opacity .15s,transform .15s}.dropdown-enter-from[data-v-f47a57b0],.dropdown-leave-to[data-v-f47a57b0]{opacity:0;transform:translateY(-50%)translate(-6px)}@media (width<=768px),(height<=640px){.left-toolbar[data-v-f47a57b0]{border-radius:5px;flex-basis:36px;gap:5px;padding:6px 4px}.left-toolbar__group[data-v-f47a57b0]{gap:3px}.left-toolbar__button[data-v-f47a57b0]{border-radius:3px;width:26px;height:26px}.left-toolbar__divider[data-v-f47a57b0]{width:16px}.corner-indicator[data-v-f47a57b0]{width:7px;height:7px}.corner-indicator[data-v-f47a57b0]:after{border-bottom-width:4px;border-left-width:4px}.tool-dropdown[data-v-f47a57b0]{height:36px}}.settings-overlay[data-v-f47a57b0]{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;background:#0000004d;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.settings-modal[data-v-f47a57b0]{background:#fff;border:1px solid #e0e0e0;border-radius:12px;width:90vw;min-width:340px;max-width:420px;overflow:hidden;box-shadow:0 8px 40px #00000026}.settings-header[data-v-f47a57b0]{background:#f8f8f8;border-bottom:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:16px 20px;display:flex}.header-left[data-v-f47a57b0]{align-items:baseline;gap:8px;display:flex}.header-right[data-v-f47a57b0]{align-items:center;gap:8px;display:flex}.settings-title[data-v-f47a57b0]{color:#1a1a1a;letter-spacing:.2px;font-size:14px;font-weight:600}.settings-subtitle[data-v-f47a57b0]{color:#999;font-size:11px}.settings-close[data-v-f47a57b0]{cursor:pointer;color:#888;background:#fff;border:1px solid #e0e0e0;border-radius:6px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;transition:background .15s,color .15s,border-color .15s;display:flex}.settings-close[data-v-f47a57b0]:hover{color:#333;background:#f0f0f0;border-color:#ccc}.settings-close svg[data-v-f47a57b0]{width:14px;height:14px}.settings-body[data-v-f47a57b0]{flex-direction:column;gap:10px;padding:16px 20px;display:flex}.settings-item[data-v-f47a57b0]{background:#f8f8f8;border:1px solid #e8e8e8;border-radius:8px;padding:8px 12px}.settings-label[data-v-f47a57b0]{color:#333;cursor:pointer;justify-content:space-between;align-items:center;font-size:13px;display:flex}.settings-checkbox[data-v-f47a57b0]{cursor:pointer;accent-color:#1a1a1a;width:16px;height:16px}.settings-section-divider[data-v-f47a57b0]{align-items:center;gap:8px;margin-top:4px;display:flex}.settings-section-divider[data-v-f47a57b0]:before,.settings-section-divider[data-v-f47a57b0]:after{content:"";border-top:1px solid #e0e0e0;flex:1}.settings-section-label[data-v-f47a57b0]{color:#999;white-space:nowrap;font-size:11px}.settings-item.experimental[data-v-f47a57b0]{background:#fdf8f3;border-color:#f0e0d0}.settings-footer[data-v-f47a57b0]{background:#f8f8f8;border-top:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:12px 20px;display:flex}.footer-right[data-v-f47a57b0]{gap:8px;display:flex}.settings-btn[data-v-f47a57b0]{cursor:pointer;border:1px solid #0000;border-radius:7px;align-items:center;gap:5px;padding:6px 14px;font-size:13px;font-weight:500;line-height:1.4;transition:all .15s;display:flex}.settings-btn svg[data-v-f47a57b0]{flex-shrink:0;width:12px;height:12px}.settings-btn.reset[data-v-f47a57b0]{color:#666;background:0 0;border-color:#d0d0d0}.settings-btn.reset[data-v-f47a57b0]:hover{color:#e74c3c;background:#e74c3c14;border-color:#c0392b}.settings-btn.cancel[data-v-f47a57b0]{color:#666;background:0 0;border-color:#d0d0d0}.settings-btn.cancel[data-v-f47a57b0]:hover{color:#333;background:#f0f0f0;border-color:#bbb}.settings-btn.confirm[data-v-f47a57b0]{color:#fff;background:#1a1a1a;border-color:#1a1a1a}.settings-btn.confirm[data-v-f47a57b0]:hover{background:#333;border-color:#333;transform:translateY(-1px);box-shadow:0 2px 10px #00000026}.settings-btn.confirm[data-v-f47a57b0]:active{box-shadow:none;transform:translateY(0)}.chart-wrapper[data-v-533a72a5]{--kmap-height:var(--kmap-chart-height,100%);--kmap-width:var(--kmap-chart-width,100%);width:var(--kmap-width);height:var(--kmap-height);flex-direction:column;justify-content:center;align-items:center;min-height:300px;display:flex}.chart-stage[data-v-533a72a5]{align-items:stretch;gap:8px;width:95%;height:85%;min-height:255px;display:flex}.chart-main[data-v-533a72a5]{flex:auto;align-items:stretch;gap:0;min-width:0;height:100%;display:flex;position:relative}.pane-separator-layer[data-v-533a72a5]{pointer-events:none;z-index:20;position:absolute;inset:0}.pane-separator-line[data-v-533a72a5]{opacity:1;box-sizing:border-box;border-top:1px solid #e5e7eb;height:0;transition:border-top-color .12s,border-top-width .12s,margin-top .12s,opacity .12s;position:absolute;left:0;right:0}.pane-separator-line.is-active[data-v-533a72a5]{border-top-width:2px;border-top-color:#3b82f6;margin-top:-1px}.chart-stage.is-resizing-pane[data-v-533a72a5],.chart-stage.is-hovering-pane-separator[data-v-533a72a5]{cursor:ns-resize}.chart-stage.is-hovering-kline[data-v-533a72a5]{cursor:pointer}.chart-stage.is-hovering-right-axis[data-v-533a72a5]{cursor:ns-resize}.chart-stage.is-dragging[data-v-533a72a5]{cursor:grabbing}.chart-container[data-v-533a72a5]{height:100%;min-height:inherit;scrollbar-width:none;-ms-overflow-style:none;box-sizing:border-box;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;touch-action:none;background:#fff;border:1px solid #e5e7eb;border-right:0;border-radius:6px 0 0 6px;flex:auto;position:relative;overflow:auto hidden}.chart-container[data-v-533a72a5]::-webkit-scrollbar{display:none}.chart-container[data-v-533a72a5]:hover{cursor:crosshair}.chart-stage.is-resizing-pane .chart-container[data-v-533a72a5],.chart-stage.is-hovering-pane-separator .chart-container[data-v-533a72a5]{cursor:ns-resize}.chart-stage.is-hovering-kline .chart-container[data-v-533a72a5]{cursor:pointer}.chart-stage.is-dragging .chart-container[data-v-533a72a5]{cursor:grabbing}.right-axis-host[data-v-533a72a5]{height:100%;min-height:inherit;box-sizing:border-box;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;touch-action:none;background:#fff;border:1px solid #e5e7eb;border-top-right-radius:6px;border-bottom-right-radius:6px;flex:none;position:relative;overflow:visible}.scroll-content[data-v-533a72a5]{height:100%;min-height:inherit;position:relative}.canvas-layer[data-v-533a72a5]{pointer-events:none;position:sticky;top:0;left:0}.tooltip-layer[data-v-533a72a5]{pointer-events:none;z-index:30;position:absolute;inset:0}.tooltip-anchor[data-v-533a72a5]{pointer-events:none;width:1px;height:1px;position:absolute}.tooltip-anchor.kline-tooltip-anchor.use-anchor[data-v-533a72a5]{anchor-name:--kline-tooltip-anchor}.tooltip-anchor.marker-tooltip-anchor.use-anchor[data-v-533a72a5]{anchor-name:--marker-tooltip-anchor}@media (width<=768px),(height<=640px){.chart-stage[data-v-533a72a5]{gap:6px}}.plot-canvas{display:block;position:absolute;top:0;left:0}.right-axis{display:block;position:absolute;left:0}.x-axis-canvas{z-index:10;display:block;position:absolute;bottom:0;left:0}.right-axis{z-index:15}
|
|
1
|
+
.kline-tooltip[data-v-d0fe85e6]{z-index:10;color:#000000c7;pointer-events:none;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);background:#ffffffeb;border:1px solid #0000001f;border-radius:8px;min-width:200px;max-width:260px;padding:10px 12px;font-size:12px;line-height:1.4;position:absolute;box-shadow:0 6px 18px #0000001f}.kline-tooltip__title[data-v-d0fe85e6]{justify-content:space-between;gap:10px;margin-bottom:6px;font-weight:600;display:flex}.kline-tooltip__grid[data-v-d0fe85e6]{grid-template-columns:1fr;gap:2px;display:grid}.kline-tooltip__grid .row[data-v-d0fe85e6]{justify-content:space-between;gap:10px;display:flex}.kline-tooltip__grid .row span[data-v-d0fe85e6]:first-child{color:#0000008f}@supports (anchor-name:--kmap-anchor) and (position-anchor:--kmap-anchor){.kline-tooltip.use-anchor[data-v-d0fe85e6]{position-anchor:--kline-tooltip-anchor;left:anchor(left);top:anchor(top);position:absolute}.kline-tooltip.use-anchor.anchor-right-bottom[data-v-d0fe85e6]{transform:translate(14px,14px)}.kline-tooltip.use-anchor.anchor-left-bottom[data-v-d0fe85e6]{transform:translate(calc(-100% - 14px),14px)}}.marker-tooltip[data-v-5574cc25]{z-index:10;color:#000000c7;pointer-events:none;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);background:#ffffffeb;border:1px solid #0000001f;border-radius:8px;min-width:180px;max-width:260px;padding:10px 12px;font-size:12px;line-height:1.4;position:absolute;box-shadow:0 6px 18px #0000001f}.marker-tooltip__title[data-v-5574cc25]{justify-content:space-between;gap:10px;margin-bottom:6px;font-weight:600;display:flex}.marker-tooltip__content[data-v-5574cc25]{grid-template-columns:1fr;gap:2px;display:grid}.marker-tooltip__content .row[data-v-5574cc25]{justify-content:space-between;gap:10px;display:flex}.marker-tooltip__content .row span[data-v-5574cc25]:first-child{color:#0000008f}@supports (anchor-name:--kmap-anchor) and (position-anchor:--kmap-anchor){.marker-tooltip.use-anchor[data-v-5574cc25]{position-anchor:--marker-tooltip-anchor;left:anchor(left);top:anchor(top);position:absolute}.marker-tooltip.use-anchor.anchor-right-bottom[data-v-5574cc25]{transform:translate(12px,12px)}.marker-tooltip.use-anchor.anchor-left-bottom[data-v-5574cc25]{transform:translate(calc(-100% - 12px),12px)}}.params-overlay[data-v-bb1d1eb3]{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;background:#0000004d;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.indicator-params[data-v-bb1d1eb3]{background:#fff;border:1px solid #e0e0e0;border-radius:12px;width:90vw;min-width:340px;max-width:420px;overflow:hidden;box-shadow:0 8px 40px #00000026}.params-header[data-v-bb1d1eb3]{background:#f8f8f8;border-bottom:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:16px 20px;display:flex}.header-left[data-v-bb1d1eb3]{align-items:baseline;gap:8px;display:flex}.header-right[data-v-bb1d1eb3]{align-items:center;gap:8px;display:flex}.params-title[data-v-bb1d1eb3]{color:#1a1a1a;letter-spacing:.2px;font-size:14px;font-weight:600}.params-subtitle[data-v-bb1d1eb3]{color:#999;font-size:11px}.toggle-desc-btn[data-v-bb1d1eb3]{cursor:pointer;color:#888;background:#fff;border:1px solid #e0e0e0;border-radius:6px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;transition:all .2s;display:flex}.toggle-desc-btn[data-v-bb1d1eb3]:hover{color:#555;background:#f0f0f0;border-color:#ccc}.toggle-desc-btn.active[data-v-bb1d1eb3]{color:#fff;background:#1a1a1a;border-color:#1a1a1a}.toggle-desc-btn svg[data-v-bb1d1eb3]{width:14px;height:14px}.params-close[data-v-bb1d1eb3]{cursor:pointer;color:#888;background:#fff;border:1px solid #e0e0e0;border-radius:6px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;transition:background .15s,color .15s,border-color .15s;display:flex}.params-close[data-v-bb1d1eb3]:hover{color:#333;background:#f0f0f0;border-color:#ccc}.params-close svg[data-v-bb1d1eb3]{width:14px;height:14px}.indicator-description[data-v-bb1d1eb3]{background:#f0f7ff;border-bottom:1px solid #d6e8f5;padding:12px 20px}.indicator-description p[data-v-bb1d1eb3]{color:#2c5282;margin:0;font-size:12px;line-height:1.6}.params-body[data-v-bb1d1eb3]{flex-direction:column;gap:10px;padding:16px 20px;display:flex}.param-item[data-v-bb1d1eb3]{background:#f8f8f8;border:1px solid #e8e8e8;border-radius:8px;padding:10px 14px;transition:border-color .2s}.param-item[data-v-bb1d1eb3]:has(.param-input:focus){border-color:#bbb}.param-item.has-desc[data-v-bb1d1eb3]{padding:10px 14px 8px}.param-header[data-v-bb1d1eb3]{justify-content:space-between;align-items:center;gap:16px;display:flex}.param-label[data-v-bb1d1eb3]{flex-direction:column;gap:3px;display:flex}.param-label-text[data-v-bb1d1eb3]{color:#333;font-size:13px;font-weight:500}.param-range[data-v-bb1d1eb3]{color:#999;font-size:11px}.param-description[data-v-bb1d1eb3]{color:#666;border-top:1px dashed #e0e0e0;margin-top:8px;padding-top:8px;font-size:11px;line-height:1.5}.input-wrapper[data-v-bb1d1eb3]{background:#fff;border:1px solid #d0d0d0;border-radius:7px;align-items:stretch;height:32px;transition:border-color .2s;display:flex;overflow:hidden}.input-wrapper[data-v-bb1d1eb3]:focus-within{border-color:#999}.stepper-btn[data-v-bb1d1eb3]{cursor:pointer;color:#666;background:#f0f0f0;border:none;flex-shrink:0;justify-content:center;align-items:center;width:28px;font-size:15px;font-weight:400;line-height:1;transition:background .15s,color .15s;display:flex}.stepper-btn[data-v-bb1d1eb3]:hover:not(:disabled){color:#333;background:#e0e0e0}.stepper-btn[data-v-bb1d1eb3]:disabled{color:#ccc;cursor:not-allowed}.param-input[data-v-bb1d1eb3]{text-align:center;color:#1a1a1a;appearance:textfield;background:0 0;border:none;border-left:1px solid #e8e8e8;border-right:1px solid #e8e8e8;width:60px;font-size:13px;font-weight:600}.param-input[data-v-bb1d1eb3]::-webkit-inner-spin-button{-webkit-appearance:none}.param-input[data-v-bb1d1eb3]::-webkit-outer-spin-button{-webkit-appearance:none}.param-input[data-v-bb1d1eb3]:focus{outline:none}.params-footer[data-v-bb1d1eb3]{background:#f8f8f8;border-top:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:12px 20px;display:flex}.footer-right[data-v-bb1d1eb3]{gap:8px;display:flex}.params-btn[data-v-bb1d1eb3]{cursor:pointer;border:1px solid #0000;border-radius:7px;align-items:center;gap:5px;padding:6px 14px;font-size:13px;font-weight:500;line-height:1.4;transition:all .15s;display:flex}.params-btn svg[data-v-bb1d1eb3]{flex-shrink:0;width:12px;height:12px}.params-btn.reset[data-v-bb1d1eb3]{color:#666;background:0 0;border-color:#d0d0d0}.params-btn.reset[data-v-bb1d1eb3]:hover{color:#e74c3c;background:#e74c3c14;border-color:#c0392b}.params-btn.cancel[data-v-bb1d1eb3]{color:#666;background:0 0;border-color:#d0d0d0}.params-btn.cancel[data-v-bb1d1eb3]:hover{color:#333;background:#f0f0f0;border-color:#bbb}.params-btn.confirm[data-v-bb1d1eb3]{color:#fff;background:#1a1a1a;border-color:#1a1a1a}.params-btn.confirm[data-v-bb1d1eb3]:hover{background:#333;border-color:#333;transform:translateY(-1px);box-shadow:0 2px 10px #00000026}.params-btn.confirm[data-v-bb1d1eb3]:active{box-shadow:none;transform:translateY(0)}.overlay-enter-active[data-v-bb1d1eb3],.overlay-leave-active[data-v-bb1d1eb3]{transition:opacity .2s}.overlay-enter-from[data-v-bb1d1eb3],.overlay-leave-to[data-v-bb1d1eb3]{opacity:0}.modal-enter-active[data-v-bb1d1eb3]{transition:all .22s cubic-bezier(.34,1.56,.64,1)}.modal-leave-active[data-v-bb1d1eb3]{transition:all .16s ease-in}.modal-enter-from[data-v-bb1d1eb3]{opacity:0;transform:scale(.88)translateY(-16px)}.modal-leave-to[data-v-bb1d1eb3]{opacity:0;transform:scale(.94)translateY(8px)}.slide-enter-active[data-v-bb1d1eb3],.slide-leave-active[data-v-bb1d1eb3]{transition:all .2s;overflow:hidden}.slide-enter-from[data-v-bb1d1eb3],.slide-leave-to[data-v-bb1d1eb3]{opacity:0;max-height:0;margin-top:0;padding-top:0;padding-bottom:0}.indicator-selector[data-v-f3fbebbd]{width:80%;margin:20px;position:relative}.indicator-scroll-container[data-v-f3fbebbd]{scrollbar-width:none;-webkit-overflow-scrolling:touch;text-align:center;width:100%;overflow:auto hidden}.indicator-scroll-container[data-v-f3fbebbd]::-webkit-scrollbar{display:none}.indicator-list[data-v-f3fbebbd]{gap:8px;margin:0 auto;padding:2px;display:inline-flex}.indicator-divider[data-v-f3fbebbd]{background:#d9d9d9;align-self:center;width:1px;height:20px}.indicator-item[data-v-f3fbebbd]{align-items:center;gap:4px;display:flex}.indicator-item.draggable[data-v-f3fbebbd],.indicator-item.draggable .indicator-btn[data-v-f3fbebbd],.indicator-item.draggable[data-v-f3fbebbd]:hover,.indicator-item.draggable:hover .indicator-btn[data-v-f3fbebbd]{cursor:move}.indicator-item.is-dragging[data-v-f3fbebbd]{opacity:.6}.indicator-item.drag-over .indicator-btn[data-v-f3fbebbd]{border-color:#1a1a1a;box-shadow:0 0 0 2px #1a1a1a1f}.indicator-btn-wrapper[data-v-f3fbebbd]{position:relative}.indicator-btn[data-v-f3fbebbd]{color:#666;cursor:pointer;white-space:nowrap;background:#fff;border:1px solid #e0e0e0;border-radius:16px;flex-shrink:0;justify-content:center;align-items:center;gap:4px;padding:6px 16px;font-size:13px;font-weight:500;transition:all .3s;display:flex;position:relative;overflow:hidden}.indicator-btn[data-v-f3fbebbd]:hover:not(.hovering){color:#333;background:#f8f8f8;border-color:#ccc}.indicator-btn.active[data-v-f3fbebbd]{color:#1a1a1a;background:#f8f8f8;border-color:#1a1a1a}.indicator-btn.active[data-v-f3fbebbd]:hover:not(.hovering){background:#f0f0f0;border-color:#333}.btn-content[data-v-f3fbebbd]{z-index:1;position:relative}.param-hint[data-v-f3fbebbd]{opacity:.85;font-size:11px}.hover-overlay[data-v-f3fbebbd]{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:2;background:#ffffffd9;border-radius:16px;justify-content:center;align-items:center;gap:4px;display:flex;position:absolute;inset:0}.action-btn[data-v-f3fbebbd]{color:#666;cursor:pointer;background:0 0;border:none;border-radius:50%;justify-content:center;align-items:center;width:24px;height:24px;padding:0;transition:all .2s;display:flex}.action-btn[data-v-f3fbebbd]:hover{color:#333;background:#0000000f}.settings-btn[data-v-f3fbebbd]:hover{color:#1a1a1a}.remove-btn[data-v-f3fbebbd]:hover{color:#ff4d4f}.divider[data-v-f3fbebbd]{background:#e0e0e0;width:1px;height:14px}.add-btn[data-v-f3fbebbd]{anchor-name:--indicator-add-btn;color:#999;cursor:pointer;background:0 0;border:1px dashed #d9d9d9;border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;width:32px;height:32px;padding:0;transition:all .3s;display:flex}.add-btn[data-v-f3fbebbd]:hover{color:#1a1a1a;background:#1a1a1a0a;border-color:#1a1a1a}.add-menu[data-v-f3fbebbd]{white-space:nowrap;z-index:9999;background:#fff;border-radius:8px;padding:8px 0;position:fixed;transform:translate(-50%);box-shadow:0 6px 16px #00000014,0 3px 6px -4px #0000001f,0 9px 28px 8px #0000000d}@supports (anchor-name:--kmap-anchor) and (position-anchor:--kmap-anchor){.add-menu.use-anchor[data-v-f3fbebbd]{position-anchor:--indicator-add-btn;left:anchor(center);top:anchor(top);max-width:calc(100vw - 16px);position:fixed;transform:translate(-50%,calc(-100% - 8px))}}.menu-section[data-v-f3fbebbd]{padding:4px 0}.menu-section[data-v-f3fbebbd]:not(:last-child){border-bottom:1px solid #f0f0f0}.menu-title[data-v-f3fbebbd]{color:#999;padding:4px 16px;font-size:12px;font-weight:500}.menu-items[data-v-f3fbebbd]{flex-direction:column;gap:2px;display:flex}.menu-item[data-v-f3fbebbd]{text-align:left;color:#333;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;width:100%;padding:8px 16px;font-size:13px;transition:background .2s;display:flex}.menu-item[data-v-f3fbebbd]:hover:not(.disabled){background:#f5f5f5}.menu-item.disabled[data-v-f3fbebbd]{color:#999;cursor:not-allowed}.menu-item .param-hint[data-v-f3fbebbd]{color:#999;font-size:11px}.active-tag[data-v-f3fbebbd]{color:#1a1a1a;align-items:center;margin-left:auto;display:flex}.fade-enter-active[data-v-f3fbebbd],.fade-leave-active[data-v-f3fbebbd]{transition:opacity .2s}.fade-enter-from[data-v-f3fbebbd],.fade-leave-to[data-v-f3fbebbd]{opacity:0}.slide-enter-active[data-v-f3fbebbd],.slide-leave-active[data-v-f3fbebbd]{transition:all .2s}.slide-enter-from[data-v-f3fbebbd],.slide-leave-to[data-v-f3fbebbd]{opacity:0;transform:translate(-50%)translateY(8px)}.drawing-style-toolbar[data-v-92699cb2]{-webkit-backdrop-filter:blur(8px);z-index:100;-webkit-user-select:none;user-select:none;pointer-events:auto;background:#fafbfce0;border:1px solid #e5e7eb;border-radius:6px;align-items:center;gap:6px;height:32px;padding:4px 8px;display:flex;position:absolute;top:8px;left:50%;transform:translate(-50%);box-shadow:0 1px 3px #0000000f}.toolbar-item[data-v-92699cb2]{justify-content:center;align-items:center;display:inline-flex}.color-item[data-v-92699cb2]{width:24px;height:24px;position:relative}.color-swatch[data-v-92699cb2]{cursor:pointer;border:1px solid #d1d5db;border-radius:4px;width:100%;height:100%;display:block}.color-input[data-v-92699cb2]{opacity:0;cursor:pointer;width:100%;height:100%;position:absolute;inset:0}.toolbar-select[data-v-92699cb2]{color:#374151;cursor:pointer;background:#fff;border:1px solid #d1d5db;border-radius:4px;outline:none;height:24px;padding:0 4px;font-size:12px}.toolbar-select[data-v-92699cb2]:hover{border-color:#9ca3af}.toolbar-btn[data-v-92699cb2]{color:#6b7280;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:4px;justify-content:center;align-items:center;width:24px;height:24px;padding:0;transition:border-color .15s,background .15s,color .15s;display:inline-flex}.toolbar-btn[data-v-92699cb2]:hover{color:#374151;background:#f3f4f6;border-color:#d1d5db}.delete-btn[data-v-92699cb2]:hover{color:#dc2626;background:#fef2f2;border-color:#fca5a5}.delete-icon[data-v-92699cb2]{width:14px;height:14px}.left-toolbar[data-v-3bc8355a]{box-sizing:border-box;-webkit-user-select:none;user-select:none;background:#fafbfc;border:1px solid #e5e7eb;border-radius:6px;flex-direction:column;flex:0 0 40px;align-items:center;gap:6px;padding:8px 5px;display:flex;box-shadow:0 1px 3px #0000000f}.left-toolbar__group[data-v-3bc8355a]{flex-direction:column;gap:4px;display:flex}.left-toolbar__divider[data-v-3bc8355a]{background:#e5e7eb;width:18px;height:1px}.left-toolbar__button[data-v-3bc8355a]{color:#6b7280;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:4px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;transition:border-color .15s,background .15s,color .15s;display:inline-flex;position:relative}.left-toolbar__button[data-v-3bc8355a]:hover{color:#374151;background:#f3f4f6;border-color:#d1d5db}.left-toolbar__button.active[data-v-3bc8355a]{color:#1f2937;background:#e5e7eb;border-color:#9ca3af}.left-toolbar__button[data-v-3bc8355a]:focus-visible{border-color:#6b7280;outline:none}.tool-icon[data-v-3bc8355a]{width:16px;height:16px}.corner-indicator[data-v-3bc8355a]{cursor:pointer;width:8px;height:8px;position:absolute;bottom:0;right:0;overflow:hidden}.corner-indicator[data-v-3bc8355a]:after{content:"";opacity:.45;border-bottom:5px solid;border-left:5px solid #0000;width:0;height:0;transition:opacity .15s;position:absolute;bottom:0;right:0}.left-toolbar__button:hover .corner-indicator[data-v-3bc8355a]:after,.left-toolbar__button.active .corner-indicator[data-v-3bc8355a]:after{opacity:.7}.corner-indicator.open[data-v-3bc8355a]:after{opacity:.8}.tool-dropdown[data-v-3bc8355a]{-webkit-backdrop-filter:blur(8px);box-sizing:border-box;z-index:100;background:#fafbfcd1;border:1px solid #e5e7eb;border-radius:6px;flex-direction:row;align-items:center;gap:4px;height:40px;padding:0 5px;display:flex;position:absolute;top:50%;left:calc(100% + 13px);transform:translateY(-50%);box-shadow:0 1px 3px #0000000f}.tool-item[data-v-3bc8355a]{position:relative}.dropdown-enter-active[data-v-3bc8355a],.dropdown-leave-active[data-v-3bc8355a]{transition:opacity .15s,transform .15s}.dropdown-enter-from[data-v-3bc8355a],.dropdown-leave-to[data-v-3bc8355a]{opacity:0;transform:translateY(-50%)translate(-6px)}@media (width<=768px),(height<=640px){.left-toolbar[data-v-3bc8355a]{border-radius:5px;flex-basis:36px;gap:5px;padding:6px 4px}.left-toolbar__group[data-v-3bc8355a]{gap:3px}.left-toolbar__button[data-v-3bc8355a]{border-radius:3px;width:26px;height:26px}.left-toolbar__divider[data-v-3bc8355a]{width:16px}.corner-indicator[data-v-3bc8355a]{width:7px;height:7px}.corner-indicator[data-v-3bc8355a]:after{border-bottom-width:4px;border-left-width:4px}.tool-dropdown[data-v-3bc8355a]{height:36px}}.settings-overlay[data-v-3bc8355a]{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;background:#0000004d;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.settings-modal[data-v-3bc8355a]{background:#fff;border:1px solid #e0e0e0;border-radius:12px;width:90vw;min-width:340px;max-width:420px;overflow:hidden;box-shadow:0 8px 40px #00000026}.settings-header[data-v-3bc8355a]{background:#f8f8f8;border-bottom:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:16px 20px;display:flex}.header-left[data-v-3bc8355a]{align-items:baseline;gap:8px;display:flex}.header-right[data-v-3bc8355a]{align-items:center;gap:8px;display:flex}.settings-title[data-v-3bc8355a]{color:#1a1a1a;letter-spacing:.2px;font-size:14px;font-weight:600}.settings-subtitle[data-v-3bc8355a]{color:#999;font-size:11px}.settings-close[data-v-3bc8355a]{cursor:pointer;color:#888;background:#fff;border:1px solid #e0e0e0;border-radius:6px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;transition:background .15s,color .15s,border-color .15s;display:flex}.settings-close[data-v-3bc8355a]:hover{color:#333;background:#f0f0f0;border-color:#ccc}.settings-close svg[data-v-3bc8355a]{width:14px;height:14px}.settings-body[data-v-3bc8355a]{flex-direction:column;gap:10px;padding:16px 20px;display:flex}.settings-item[data-v-3bc8355a]{background:#f8f8f8;border:1px solid #e8e8e8;border-radius:8px;padding:8px 12px}.settings-label[data-v-3bc8355a]{color:#333;cursor:pointer;justify-content:space-between;align-items:center;font-size:13px;display:flex}.settings-checkbox[data-v-3bc8355a]{cursor:pointer;accent-color:#1a1a1a;width:16px;height:16px}.settings-section-divider[data-v-3bc8355a]{align-items:center;gap:8px;margin-top:4px;display:flex}.settings-section-divider[data-v-3bc8355a]:before,.settings-section-divider[data-v-3bc8355a]:after{content:"";border-top:1px solid #e0e0e0;flex:1}.settings-section-label[data-v-3bc8355a]{color:#999;white-space:nowrap;font-size:11px}.settings-item.experimental[data-v-3bc8355a]{background:#fdf8f3;border-color:#f0e0d0}.settings-footer[data-v-3bc8355a]{background:#f8f8f8;border-top:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:12px 20px;display:flex}.footer-right[data-v-3bc8355a]{gap:8px;display:flex}.settings-btn[data-v-3bc8355a]{cursor:pointer;border:1px solid #0000;border-radius:7px;align-items:center;gap:5px;padding:6px 14px;font-size:13px;font-weight:500;line-height:1.4;transition:all .15s;display:flex}.settings-btn svg[data-v-3bc8355a]{flex-shrink:0;width:12px;height:12px}.settings-btn.reset[data-v-3bc8355a]{color:#666;background:0 0;border-color:#d0d0d0}.settings-btn.reset[data-v-3bc8355a]:hover{color:#e74c3c;background:#e74c3c14;border-color:#c0392b}.settings-btn.cancel[data-v-3bc8355a]{color:#666;background:0 0;border-color:#d0d0d0}.settings-btn.cancel[data-v-3bc8355a]:hover{color:#333;background:#f0f0f0;border-color:#bbb}.settings-btn.confirm[data-v-3bc8355a]{color:#fff;background:#1a1a1a;border-color:#1a1a1a}.settings-btn.confirm[data-v-3bc8355a]:hover{background:#333;border-color:#333;transform:translateY(-1px);box-shadow:0 2px 10px #00000026}.settings-btn.confirm[data-v-3bc8355a]:active{box-shadow:none;transform:translateY(0)}.chart-wrapper[data-v-e5d29a39]{--kmap-height:var(--kmap-chart-height,100%);--kmap-width:var(--kmap-chart-width,100%);width:var(--kmap-width);height:var(--kmap-height);flex-direction:column;justify-content:center;align-items:center;min-height:300px;display:flex}.chart-stage[data-v-e5d29a39]{align-items:stretch;gap:8px;width:95%;height:85%;min-height:255px;display:flex}.chart-main[data-v-e5d29a39]{flex:auto;align-items:stretch;gap:0;min-width:0;height:100%;display:flex;position:relative}.pane-separator-layer[data-v-e5d29a39]{pointer-events:none;z-index:20;position:absolute;inset:0}.pane-separator-line[data-v-e5d29a39]{opacity:1;box-sizing:border-box;border-top:1px solid #e5e7eb;height:0;transition:border-top-color .12s,border-top-width .12s,margin-top .12s,opacity .12s;position:absolute;left:0;right:0}.pane-separator-line.is-active[data-v-e5d29a39]{border-top-width:2px;border-top-color:#3b82f6;margin-top:-1px}.chart-stage.is-resizing-pane[data-v-e5d29a39],.chart-stage.is-hovering-pane-separator[data-v-e5d29a39]{cursor:ns-resize}.chart-stage.is-hovering-kline[data-v-e5d29a39]{cursor:pointer}.chart-stage.is-hovering-right-axis[data-v-e5d29a39]{cursor:ns-resize}.chart-stage.is-dragging[data-v-e5d29a39]{cursor:grabbing}.chart-container[data-v-e5d29a39]{height:100%;min-height:inherit;scrollbar-width:none;-ms-overflow-style:none;box-sizing:border-box;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;touch-action:none;background:#fff;border:1px solid #e5e7eb;border-right:0;border-radius:6px 0 0 6px;flex:auto;position:relative;overflow:auto hidden}.chart-container[data-v-e5d29a39]::-webkit-scrollbar{display:none}.chart-container[data-v-e5d29a39]:hover{cursor:crosshair}.chart-stage.is-resizing-pane .chart-container[data-v-e5d29a39],.chart-stage.is-hovering-pane-separator .chart-container[data-v-e5d29a39]{cursor:ns-resize}.chart-stage.is-hovering-kline .chart-container[data-v-e5d29a39]{cursor:pointer}.chart-stage.is-dragging .chart-container[data-v-e5d29a39]{cursor:grabbing}.right-axis-host[data-v-e5d29a39]{height:100%;min-height:inherit;box-sizing:border-box;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;touch-action:none;background:#fff;border:1px solid #e5e7eb;border-top-right-radius:6px;border-bottom-right-radius:6px;flex:none;position:relative;overflow:visible}.scroll-content[data-v-e5d29a39]{height:100%;min-height:inherit;position:relative}.canvas-layer[data-v-e5d29a39]{pointer-events:none;position:sticky;top:0;left:0}.tooltip-layer[data-v-e5d29a39]{pointer-events:none;z-index:30;position:absolute;inset:0}.tooltip-anchor[data-v-e5d29a39]{pointer-events:none;width:1px;height:1px;position:absolute}.tooltip-anchor.kline-tooltip-anchor.use-anchor[data-v-e5d29a39]{anchor-name:--kline-tooltip-anchor}.tooltip-anchor.marker-tooltip-anchor.use-anchor[data-v-e5d29a39]{anchor-name:--marker-tooltip-anchor}@media (width<=768px),(height<=640px){.chart-stage[data-v-e5d29a39]{gap:6px}}.plot-canvas{display:block;position:absolute;top:0;left:0}.right-axis{display:block;position:absolute;left:0}.x-axis-canvas{z-index:10;display:block;position:absolute;bottom:0;left:0}.right-axis{z-index:15}
|
|
2
2
|
/*$vite$:1*/
|
|
@@ -8,12 +8,16 @@ export interface SettingItem {
|
|
|
8
8
|
default: boolean;
|
|
9
9
|
group?: string;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* 检测是否为移动端设备
|
|
13
|
+
*/
|
|
14
|
+
export declare function isMobileDevice(): boolean;
|
|
11
15
|
/** 默认设置配置 */
|
|
12
16
|
export declare const DEFAULT_SETTINGS: readonly [{
|
|
13
17
|
readonly key: "showVolumePriceMarkers";
|
|
14
18
|
readonly label: "显示量价关系标记";
|
|
15
19
|
readonly type: "boolean";
|
|
16
|
-
readonly default:
|
|
20
|
+
readonly default: false;
|
|
17
21
|
readonly group: "main";
|
|
18
22
|
}, {
|
|
19
23
|
readonly key: "logarithmicScale";
|
|
@@ -21,6 +25,12 @@ export declare const DEFAULT_SETTINGS: readonly [{
|
|
|
21
25
|
readonly type: "boolean";
|
|
22
26
|
readonly default: false;
|
|
23
27
|
readonly group: "main";
|
|
28
|
+
}, {
|
|
29
|
+
readonly key: "enableWebGLRendering";
|
|
30
|
+
readonly label: "启用 WebGL 硬件加速渲染";
|
|
31
|
+
readonly type: "boolean";
|
|
32
|
+
readonly default: true;
|
|
33
|
+
readonly group: "main";
|
|
24
34
|
}, {
|
|
25
35
|
readonly key: "disableMainPaneVerticalScroll";
|
|
26
36
|
readonly label: "主图纵轴刻度自适应调整";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { KLineData } from '../../types/price';
|
|
2
|
+
import { KLineSoALayout } from './soa';
|
|
2
3
|
/**
|
|
3
4
|
* MA 周期配置标志
|
|
4
5
|
*/
|
|
@@ -127,3 +128,142 @@ export interface KSTPoint {
|
|
|
127
128
|
export declare function calcKSTData(data: KLineData[], roc1: number, roc2: number, roc3: number, roc4: number, signalPeriod: number): KSTPoint[];
|
|
128
129
|
export declare const DEFAULT_FASTK_PERIOD = 9;
|
|
129
130
|
export declare function calcFASTKData(data: KLineData[], period: number): (number | undefined)[];
|
|
131
|
+
/**
|
|
132
|
+
* MACD 数据点
|
|
133
|
+
*/
|
|
134
|
+
export interface MACDPoint {
|
|
135
|
+
/** DIF 线值 */
|
|
136
|
+
dif: number;
|
|
137
|
+
/** DEA 线值 */
|
|
138
|
+
dea: number;
|
|
139
|
+
/** MACD 柱状图值 */
|
|
140
|
+
macd: number;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* 默认 MACD 参数
|
|
144
|
+
*/
|
|
145
|
+
export declare const DEFAULT_MACD_FAST_PERIOD = 12;
|
|
146
|
+
export declare const DEFAULT_MACD_SLOW_PERIOD = 26;
|
|
147
|
+
export declare const DEFAULT_MACD_SIGNAL_PERIOD = 9;
|
|
148
|
+
/**
|
|
149
|
+
* 计算 EMA(指数移动平均)值
|
|
150
|
+
* EMA(today) = close × K + EMA(yesterday) × (1 - K)
|
|
151
|
+
* K = 2 / (period + 1)
|
|
152
|
+
* @param data K线数据数组
|
|
153
|
+
* @param period 周期
|
|
154
|
+
* @returns EMA 值数组,第一个值使用第一个收盘价
|
|
155
|
+
*/
|
|
156
|
+
export declare function calcEMA(data: KLineData[], period: number): number[];
|
|
157
|
+
/**
|
|
158
|
+
* 基于数值数组计算 EMA
|
|
159
|
+
* @param values 数值数组(可能包含 undefined)
|
|
160
|
+
* @param period 周期
|
|
161
|
+
* @returns EMA 值数组
|
|
162
|
+
*/
|
|
163
|
+
export declare function calcEMAFromArray(values: (number | undefined)[], period: number): (number | undefined)[];
|
|
164
|
+
/**
|
|
165
|
+
* 计算 MACD 数据
|
|
166
|
+
* DIF = EMA(close, fastPeriod) - EMA(close, slowPeriod)
|
|
167
|
+
* DEA = EMA(DIF, signalPeriod)
|
|
168
|
+
* MACD = (DIF - DEA) × 2
|
|
169
|
+
* @param data K线数据数组
|
|
170
|
+
* @param fastPeriod 快线周期(默认12)
|
|
171
|
+
* @param slowPeriod 慢线周期(默认26)
|
|
172
|
+
* @param signalPeriod 信号线周期(默认9)
|
|
173
|
+
* @returns MACD 数据点数组,前 slowPeriod-1 个可能为 undefined
|
|
174
|
+
*/
|
|
175
|
+
export declare function calcMACDData(data: KLineData[], fastPeriod: number, slowPeriod: number, signalPeriod: number): MACDPoint[];
|
|
176
|
+
/**
|
|
177
|
+
* 从 SoA 布局计算 BOLL 数据(验证用包装函数)
|
|
178
|
+
* @param layout SoA 布局
|
|
179
|
+
* @param period 周期
|
|
180
|
+
* @param multiplier 标准差倍数
|
|
181
|
+
* @returns BOLL 数据点数组
|
|
182
|
+
*/
|
|
183
|
+
export declare function calcBOLLDataSoA(layout: KLineSoALayout, period: number, multiplier: number): BOLLPoint[];
|
|
184
|
+
/**
|
|
185
|
+
* 从 SoA 布局计算 EXPMA 数据(验证用包装函数)
|
|
186
|
+
* @param layout SoA 布局
|
|
187
|
+
* @param fastPeriod 快线周期
|
|
188
|
+
* @param slowPeriod 慢线周期
|
|
189
|
+
* @returns EXPMA 数据点数组
|
|
190
|
+
*/
|
|
191
|
+
export declare function calcEXPMADataSoA(layout: KLineSoALayout, fastPeriod: number, slowPeriod: number): EXPMAPoint[];
|
|
192
|
+
/**
|
|
193
|
+
* 从 SoA 布局计算 ENE 数据(验证用包装函数)
|
|
194
|
+
* @param layout SoA 布局
|
|
195
|
+
* @param period 周期
|
|
196
|
+
* @param deviation 偏离率百分比
|
|
197
|
+
* @returns ENE 数据点数组
|
|
198
|
+
*/
|
|
199
|
+
export declare function calcENEDataSoA(layout: KLineSoALayout, period: number, deviation: number): ENEPoint[];
|
|
200
|
+
/**
|
|
201
|
+
* 从 SoA 布局计算 MA 数据(验证用包装函数)
|
|
202
|
+
* @param layout SoA 布局
|
|
203
|
+
* @param period MA周期
|
|
204
|
+
* @returns MA 值数组
|
|
205
|
+
*/
|
|
206
|
+
export declare function calcMADataSoA(layout: KLineSoALayout, period: number): (number | undefined)[];
|
|
207
|
+
/**
|
|
208
|
+
* 从 SoA 布局计算 RSI 数据(验证用包装函数)
|
|
209
|
+
* @param layout SoA 布局
|
|
210
|
+
* @param period RSI周期
|
|
211
|
+
* @returns RSI 值数组
|
|
212
|
+
*/
|
|
213
|
+
export declare function calcRSIDataSoA(layout: KLineSoALayout, period: number): (number | undefined)[];
|
|
214
|
+
/**
|
|
215
|
+
* 从 SoA 布局计算 CCI 数据(验证用包装函数)
|
|
216
|
+
* @param layout SoA 布局
|
|
217
|
+
* @param period 周期
|
|
218
|
+
* @returns CCI 值数组
|
|
219
|
+
*/
|
|
220
|
+
export declare function calcCCIDataSoA(layout: KLineSoALayout, period: number): (number | undefined)[];
|
|
221
|
+
/**
|
|
222
|
+
* 从 SoA 布局计算 STOCH 数据(验证用包装函数)
|
|
223
|
+
* @param layout SoA 布局
|
|
224
|
+
* @param n RSV周期
|
|
225
|
+
* @param m K的M日移动平均周期
|
|
226
|
+
* @returns STOCH 数据点数组
|
|
227
|
+
*/
|
|
228
|
+
export declare function calcSTOCHDataSoA(layout: KLineSoALayout, n: number, m: number): STOCHPoint[];
|
|
229
|
+
/**
|
|
230
|
+
* 从 SoA 布局计算 MOM 数据(验证用包装函数)
|
|
231
|
+
* @param layout SoA 布局
|
|
232
|
+
* @param period 周期
|
|
233
|
+
* @returns MOM 值数组
|
|
234
|
+
*/
|
|
235
|
+
export declare function calcMOMDataSoA(layout: KLineSoALayout, period: number): (number | undefined)[];
|
|
236
|
+
/**
|
|
237
|
+
* 从 SoA 布局计算 WMSR 数据(验证用包装函数)
|
|
238
|
+
* @param layout SoA 布局
|
|
239
|
+
* @param period 周期
|
|
240
|
+
* @returns WMSR 值数组
|
|
241
|
+
*/
|
|
242
|
+
export declare function calcWMSRDataSoA(layout: KLineSoALayout, period: number): (number | undefined)[];
|
|
243
|
+
/**
|
|
244
|
+
* 从 SoA 布局计算 KST 数据(验证用包装函数)
|
|
245
|
+
* @param layout SoA 布局
|
|
246
|
+
* @param roc1 第一个ROC周期
|
|
247
|
+
* @param roc2 第二个ROC周期
|
|
248
|
+
* @param roc3 第三个ROC周期
|
|
249
|
+
* @param roc4 第四个ROC周期
|
|
250
|
+
* @param signalPeriod 信号线周期
|
|
251
|
+
* @returns KST 数据点数组
|
|
252
|
+
*/
|
|
253
|
+
export declare function calcKSTDataSoA(layout: KLineSoALayout, roc1: number, roc2: number, roc3: number, roc4: number, signalPeriod: number): KSTPoint[];
|
|
254
|
+
/**
|
|
255
|
+
* 从 SoA 布局计算 FASTK 数据(验证用包装函数)
|
|
256
|
+
* @param layout SoA 布局
|
|
257
|
+
* @param period 周期
|
|
258
|
+
* @returns FASTK 值数组
|
|
259
|
+
*/
|
|
260
|
+
export declare function calcFASTKDataSoA(layout: KLineSoALayout, period: number): (number | undefined)[];
|
|
261
|
+
/**
|
|
262
|
+
* 从 SoA 布局计算 MACD 数据(验证用包装函数)
|
|
263
|
+
* @param layout SoA 布局
|
|
264
|
+
* @param fastPeriod 快线周期
|
|
265
|
+
* @param slowPeriod 慢线周期
|
|
266
|
+
* @param signalPeriod 信号线周期
|
|
267
|
+
* @returns MACD 数据点数组
|
|
268
|
+
*/
|
|
269
|
+
export declare function calcMACDDataSoA(layout: KLineSoALayout, fastPeriod: number, slowPeriod: number, signalPeriod: number): MACDPoint[];
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { BaseIndicatorState } from '../../plugin';
|
|
2
|
+
import { MACDPoint } from './calculators';
|
|
3
|
+
/**
|
|
4
|
+
* MACD 调度器配置
|
|
5
|
+
*/
|
|
6
|
+
export interface MACDSchedulerConfig {
|
|
7
|
+
/** 快线周期(默认 12) */
|
|
8
|
+
fastPeriod: number;
|
|
9
|
+
/** 慢线周期(默认 26) */
|
|
10
|
+
slowPeriod: number;
|
|
11
|
+
/** DEA 周期(默认 9) */
|
|
12
|
+
signalPeriod: number;
|
|
13
|
+
/** 是否显示 DIF 线 */
|
|
14
|
+
showDIF: boolean;
|
|
15
|
+
/** 是否显示 DEA 线 */
|
|
16
|
+
showDEA: boolean;
|
|
17
|
+
/** 是否显示 MACD 柱 */
|
|
18
|
+
showBAR: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* MACD 渲染器状态
|
|
22
|
+
* 用 Record 而非 Map,兼容 JSON 序列化和 postMessage
|
|
23
|
+
*/
|
|
24
|
+
export interface MACDRenderState extends BaseIndicatorState {
|
|
25
|
+
/** MACD 系列数据,与 K 线数据同长度 */
|
|
26
|
+
series: MACDPoint[];
|
|
27
|
+
/** 配置参数 */
|
|
28
|
+
params: MACDSchedulerConfig;
|
|
29
|
+
/** 可视范围内的最小值 */
|
|
30
|
+
visibleMin: number;
|
|
31
|
+
/** 可视范围内的最大值 */
|
|
32
|
+
visibleMax: number;
|
|
33
|
+
/** 固定数值范围最小值 */
|
|
34
|
+
valueMin: number;
|
|
35
|
+
/** 固定数值范围最大值 */
|
|
36
|
+
valueMax: number;
|
|
37
|
+
/** 最新值 */
|
|
38
|
+
latestValues?: {
|
|
39
|
+
dif: number;
|
|
40
|
+
dea: number;
|
|
41
|
+
macd: number;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* MACD State 的命名空间 key
|
|
46
|
+
* 格式: indicator:macd:{paneId}
|
|
47
|
+
*/
|
|
48
|
+
export declare const MACD_STATE_KEY = "indicator:macd";
|
|
49
|
+
/**
|
|
50
|
+
* 创建 MACD State Key
|
|
51
|
+
* @param paneId pane ID,如 'sub_MACD'
|
|
52
|
+
*/
|
|
53
|
+
export declare function createMACDStateKey(paneId: string): string;
|
|
54
|
+
/**
|
|
55
|
+
* 空 MACD State(哨兵值)
|
|
56
|
+
* visibleMin > visibleMax 表示无有效数据
|
|
57
|
+
*/
|
|
58
|
+
export declare const EMPTY_MACD_STATE: MACDRenderState;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { PluginHost } from '../../plugin';
|
|
2
2
|
import { KLineData } from '../../types/price';
|
|
3
3
|
import { MAFlags } from './calculators';
|
|
4
|
+
import { MACDSchedulerConfig } from './macdState';
|
|
4
5
|
/**
|
|
5
6
|
* 可见范围
|
|
6
7
|
*/
|
|
@@ -138,6 +139,9 @@ export declare class IndicatorScheduler {
|
|
|
138
139
|
private fastkConfig;
|
|
139
140
|
private fastkPaneId;
|
|
140
141
|
private cachedFastkSeries;
|
|
142
|
+
private macdConfig;
|
|
143
|
+
private macdPaneId;
|
|
144
|
+
private cachedMacdSeries;
|
|
141
145
|
private dirtyData;
|
|
142
146
|
private dirtyRange;
|
|
143
147
|
private dirtyBollConfig;
|
|
@@ -150,6 +154,7 @@ export declare class IndicatorScheduler {
|
|
|
150
154
|
private dirtyWmsrConfig;
|
|
151
155
|
private dirtyKstConfig;
|
|
152
156
|
private dirtyFastkConfig;
|
|
157
|
+
private dirtyMacdConfig;
|
|
153
158
|
private dirtyRsiState;
|
|
154
159
|
private dirtyCciState;
|
|
155
160
|
private dirtyStochState;
|
|
@@ -157,6 +162,7 @@ export declare class IndicatorScheduler {
|
|
|
157
162
|
private dirtyWmsrState;
|
|
158
163
|
private dirtyKstState;
|
|
159
164
|
private dirtyFastkState;
|
|
165
|
+
private dirtyMacdState;
|
|
160
166
|
/** 当前激活的主图指标列表 */
|
|
161
167
|
private activeMainIndicators;
|
|
162
168
|
/**
|
|
@@ -236,6 +242,12 @@ export declare class IndicatorScheduler {
|
|
|
236
242
|
* @param paneId FASTK pane ID(可选,默认 'sub_FASTK')
|
|
237
243
|
*/
|
|
238
244
|
updateFASTKConfig(config: Partial<FASTKSchedulerConfig>, paneId?: string): void;
|
|
245
|
+
/**
|
|
246
|
+
* MACD 配置变更时调用
|
|
247
|
+
* @param config 新的 MACD 配置
|
|
248
|
+
* @param paneId MACD pane ID(可选,默认 'sub_MACD')
|
|
249
|
+
*/
|
|
250
|
+
updateMACDConfig(config: Partial<MACDSchedulerConfig>, paneId?: string): void;
|
|
239
251
|
/**
|
|
240
252
|
* 视口变更时调用
|
|
241
253
|
* @param visibleRange 新的可见范围
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { KLineData } from '../../types/price';
|
|
2
|
+
/**
|
|
3
|
+
* KLineData 的 SoA (Structure of Arrays) 布局
|
|
4
|
+
* 用于零拷贝传输到 Web Worker
|
|
5
|
+
*
|
|
6
|
+
* 内存布局:
|
|
7
|
+
* | timestamps | opens | highs | lows | closes | volumes | turnovers |
|
|
8
|
+
* | 8*N | 8*N | 8*N | 8*N | 8*N | 8*N | 8*N |
|
|
9
|
+
*
|
|
10
|
+
* 其中 N 为数据长度,每列 8 字节(Float64)
|
|
11
|
+
*/
|
|
12
|
+
export interface KLineSoALayout {
|
|
13
|
+
/** 底层缓冲区(SharedArrayBuffer 或 ArrayBuffer) */
|
|
14
|
+
buffer: SharedArrayBuffer | ArrayBuffer;
|
|
15
|
+
/** 数据长度 */
|
|
16
|
+
length: number;
|
|
17
|
+
/** 是否使用 SharedArrayBuffer */
|
|
18
|
+
isShared: boolean;
|
|
19
|
+
/** 是否有成交量数据 */
|
|
20
|
+
hasVolume: boolean;
|
|
21
|
+
/** 是否有成交额数据 */
|
|
22
|
+
hasTurnover: boolean;
|
|
23
|
+
/** 时间戳数组(毫秒) */
|
|
24
|
+
timestamps: Float64Array;
|
|
25
|
+
/** 开盘价数组 */
|
|
26
|
+
opens: Float64Array;
|
|
27
|
+
/** 最高价数组 */
|
|
28
|
+
highs: Float64Array;
|
|
29
|
+
/** 最低价数组 */
|
|
30
|
+
lows: Float64Array;
|
|
31
|
+
/** 收盘价数组 */
|
|
32
|
+
closes: Float64Array;
|
|
33
|
+
/** 成交量数组(无值时为 0) */
|
|
34
|
+
volumes: Float64Array;
|
|
35
|
+
/** 成交额数组(无值时为 0) */
|
|
36
|
+
turnovers: Float64Array;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* SharedKLineBuffer - K线数据的 SoA 管理类
|
|
40
|
+
*
|
|
41
|
+
* 提供 AoS (KLineData[]) 与 SoA 布局之间的转换,
|
|
42
|
+
* 支持 SharedArrayBuffer(零拷贝)和 ArrayBuffer(降级)
|
|
43
|
+
*/
|
|
44
|
+
export declare class SharedKLineBuffer {
|
|
45
|
+
/**
|
|
46
|
+
* 检测 SharedArrayBuffer 是否可用
|
|
47
|
+
* 需要页面有 COOP/COEP 头支持
|
|
48
|
+
*/
|
|
49
|
+
static detectSupport(): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* 计算 SoA 布局所需的总字节数
|
|
52
|
+
*/
|
|
53
|
+
static calculateByteLength(length: number): number;
|
|
54
|
+
/**
|
|
55
|
+
* 将 KLineData[] 转换为 SoA 布局
|
|
56
|
+
* @param data K线数据数组(AoS 格式)
|
|
57
|
+
* @param preferShared 是否优先使用 SharedArrayBuffer(默认 true)
|
|
58
|
+
* @returns SoA 布局对象
|
|
59
|
+
*/
|
|
60
|
+
static fromKLineData(data: KLineData[], preferShared?: boolean): KLineSoALayout;
|
|
61
|
+
/**
|
|
62
|
+
* 更新现有 SoA 布局的数据(尽可能复用缓冲区)
|
|
63
|
+
* 如果新数据长度超过原缓冲区,会创建新缓冲区
|
|
64
|
+
*
|
|
65
|
+
* @param layout 现有 SoA 布局
|
|
66
|
+
* @param data 新的 K线数据
|
|
67
|
+
* @returns 更新后的 SoA 布局(可能是新对象)
|
|
68
|
+
*/
|
|
69
|
+
static updateExisting(layout: KLineSoALayout, data: KLineData[]): KLineSoALayout;
|
|
70
|
+
/**
|
|
71
|
+
* 将 SoA 布局转换回 KLineData[](用于测试和兼容性)
|
|
72
|
+
* @param layout SoA 布局
|
|
73
|
+
* @returns K线数据数组
|
|
74
|
+
*/
|
|
75
|
+
static toKLineData(layout: KLineSoALayout): KLineData[];
|
|
76
|
+
/**
|
|
77
|
+
* 创建子视图(用于 Worker 中处理部分数据范围)
|
|
78
|
+
* @param layout 原 SoA 布局
|
|
79
|
+
* @param start 起始索引(包含)
|
|
80
|
+
* @param end 结束索引(不包含)
|
|
81
|
+
* @returns 子视图对象(共享同一缓冲区)
|
|
82
|
+
*/
|
|
83
|
+
static createSubview(layout: KLineSoALayout, start: number, end: number): KLineSoALayout;
|
|
84
|
+
/**
|
|
85
|
+
* 获取缓冲区信息(用于调试和序列化)
|
|
86
|
+
*/
|
|
87
|
+
static getBufferInfo(layout: KLineSoALayout): {
|
|
88
|
+
byteLength: number;
|
|
89
|
+
isShared: boolean;
|
|
90
|
+
length: number;
|
|
91
|
+
columns: string[];
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* 获取 SoA 布局中 closes 列的视图(最常用列)
|
|
96
|
+
* 用于指标计算中快速访问收盘价
|
|
97
|
+
*/
|
|
98
|
+
export declare function getClosesView(layout: KLineSoALayout): Float64Array;
|
|
99
|
+
/**
|
|
100
|
+
* 获取 SoA 布局中 highs/lows 列的视图
|
|
101
|
+
* 用于需要高低价的指标(如 BOLL、STOCH、WMSR)
|
|
102
|
+
*/
|
|
103
|
+
export declare function getHighsLowsViews(layout: KLineSoALayout): {
|
|
104
|
+
highs: Float64Array;
|
|
105
|
+
lows: Float64Array;
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* 获取 SoA 布局中 OHLC 四价视图
|
|
109
|
+
*/
|
|
110
|
+
export declare function getOHLCViews(layout: KLineSoALayout): {
|
|
111
|
+
opens: Float64Array;
|
|
112
|
+
highs: Float64Array;
|
|
113
|
+
lows: Float64Array;
|
|
114
|
+
closes: Float64Array;
|
|
115
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RendererPluginWithHost
|
|
1
|
+
import { RendererPluginWithHost } from '../../../plugin';
|
|
2
2
|
import { KLineData } from '../../../types/price';
|
|
3
3
|
export interface MACDConfig {
|
|
4
4
|
/** 快线周期(默认 12) */
|
|
@@ -14,16 +14,6 @@ export interface MACDConfig {
|
|
|
14
14
|
/** 是否显示 MACD 柱 */
|
|
15
15
|
showBAR?: boolean;
|
|
16
16
|
}
|
|
17
|
-
/** MACD 渲染器状态(共享给刻度渲染器) */
|
|
18
|
-
export interface MACDRenderState extends BaseIndicatorState {
|
|
19
|
-
valueMin: number;
|
|
20
|
-
valueMax: number;
|
|
21
|
-
latestValues?: {
|
|
22
|
-
dif: number;
|
|
23
|
-
dea: number;
|
|
24
|
-
macd: number;
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
17
|
export interface MACDRendererOptions {
|
|
28
18
|
/** 目标 pane ID(默认 'sub') */
|
|
29
19
|
paneId?: string;
|
|
@@ -32,10 +22,12 @@ export interface MACDRendererOptions {
|
|
|
32
22
|
}
|
|
33
23
|
/**
|
|
34
24
|
* 创建 MACD 渲染器插件
|
|
25
|
+
* 从 StateStore 读取 MACD 状态,不再内联计算
|
|
35
26
|
*/
|
|
36
27
|
export declare function createMACDRendererPlugin(options?: MACDRendererOptions): RendererPluginWithHost;
|
|
37
28
|
/**
|
|
38
29
|
* 计算指定索引处的 MACD 值(供图例使用)
|
|
30
|
+
* 使用 calculators.ts 中的计算函数
|
|
39
31
|
*/
|
|
40
32
|
export declare function calcMACDAtIndex(data: KLineData[], index: number, fastPeriod?: number, slowPeriod?: number, signalPeriod?: number): {
|
|
41
33
|
dif: number;
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { RendererPluginWithHost, PluginHost } from '../../../plugin';
|
|
2
|
+
type LinePoint = {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
};
|
|
2
6
|
export interface RSIRendererOptions {
|
|
3
7
|
/** 目标 pane ID(默认 'sub') */
|
|
4
8
|
paneId?: string;
|
|
@@ -11,6 +15,11 @@ export declare function createRSIRendererPlugin(options?: RSIRendererOptions): R
|
|
|
11
15
|
* 获取 RSI 标题信息(供 paneTitle 使用)
|
|
12
16
|
* 从 StateStore 读取已计算的 RSI 数据
|
|
13
17
|
*/
|
|
18
|
+
export declare function drawRSILinesWithCanvas2D(ctx: CanvasRenderingContext2D, scrollLeft: number, rsi1Points: LinePoint[], rsi2Points: LinePoint[], rsi3Points: LinePoint[], params: {
|
|
19
|
+
showRSI1: boolean;
|
|
20
|
+
showRSI2: boolean;
|
|
21
|
+
showRSI3: boolean;
|
|
22
|
+
}): void;
|
|
14
23
|
export declare function getRSITitleInfo(index: number, period1: number, period2: number, period3: number, pluginHost: PluginHost, paneId?: string): {
|
|
15
24
|
name: string;
|
|
16
25
|
params: number[];
|
|
@@ -20,3 +29,4 @@ export declare function getRSITitleInfo(index: number, period1: number, period2:
|
|
|
20
29
|
color: string;
|
|
21
30
|
}>;
|
|
22
31
|
} | null;
|
|
32
|
+
export {};
|
|
@@ -17,6 +17,8 @@ export declare class CandleWebGLSurface {
|
|
|
17
17
|
private logicalWidth;
|
|
18
18
|
private logicalHeight;
|
|
19
19
|
private available;
|
|
20
|
+
private rectCapacity;
|
|
21
|
+
private rectScratch;
|
|
20
22
|
constructor(canvas?: HTMLCanvasElement);
|
|
21
23
|
isAvailable(): boolean;
|
|
22
24
|
getCanvas(): HTMLCanvasElement;
|
|
@@ -33,6 +35,7 @@ export declare class LineWebGLSurface {
|
|
|
33
35
|
private logicalHeight;
|
|
34
36
|
private dpr;
|
|
35
37
|
private available;
|
|
38
|
+
private vertexCapacity;
|
|
36
39
|
constructor(canvas?: HTMLCanvasElement);
|
|
37
40
|
isAvailable(): boolean;
|
|
38
41
|
getCanvas(): HTMLCanvasElement;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@363045841yyt/klinechart",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.5",
|
|
4
4
|
"description": "A lightweight financial K-line charting library with first-class AI Agent support, crisp ResizeObserver-driven rendering, and plugin-based architecture. Focused on quantitative trading scenarios with TradingView-level interaction experience.",
|
|
5
5
|
"author": "363045841 <slslswbsy@qq.com>",
|
|
6
6
|
"license": "MIT",
|