|
13 | 13 | from .util import ( |
14 | 14 | BulkRunScript, Pane, Events, IDGen, as_enum, jbool, js_json, TIME, NUM, FLOAT, |
15 | 15 | LINE_STYLE, MARKER_POSITION, MARKER_SHAPE, CROSSHAIR_MODE, |
16 | | - PRICE_SCALE_MODE, marker_position, marker_shape, js_data, |
| 16 | + PRICE_SCALE_MODE, marker_position, marker_shape, js_data, js_zipdata |
17 | 17 | ) |
18 | 18 |
|
19 | 19 | current_dir = os.path.dirname(os.path.abspath(__file__)) |
@@ -56,7 +56,7 @@ def on_js_load(self): |
56 | 56 | self.scripts.extend(self.final_scripts) |
57 | 57 | for script in self.scripts: |
58 | 58 | initial_script += f'\n{script}' |
59 | | - self.script_func(initial_script) |
| 59 | + self.script_func(f'(async ()=> {{ {initial_script} }})();') |
60 | 60 |
|
61 | 61 | def run_script(self, script: str, run_last: bool = False): |
62 | 62 | """ |
@@ -217,6 +217,21 @@ def _single_datetime_format(self, arg) -> float: |
217 | 217 | arg = self._interval * (arg.timestamp() // self._interval)+self.offset |
218 | 218 | return arg |
219 | 219 |
|
| 220 | + def set_zipped(self, df: Optional[pd.DataFrame] = None, format_cols: bool = True): |
| 221 | + if df is None or df.empty: |
| 222 | + self.run_script(f'{self.id}.series.setData([])') |
| 223 | + self.data = pd.DataFrame() |
| 224 | + return |
| 225 | + if format_cols: |
| 226 | + df = self._df_datetime_format(df, exclude_lowercase=self.name) |
| 227 | + if self.name: |
| 228 | + if self.name not in df: |
| 229 | + raise NameError(f'No column named "{self.name}".') |
| 230 | + df = df.rename(columns={self.name: 'value'}) |
| 231 | + self.data = df.copy() |
| 232 | + self._last_bar = df.iloc[-1] |
| 233 | + self.run_script(f'{self.id}.series.setData(await decodeGzJSON("{js_zipdata(df)}")); ') |
| 234 | + |
220 | 235 | def set(self, df: Optional[pd.DataFrame] = None, format_cols: bool = True): |
221 | 236 | if df is None or df.empty: |
222 | 237 | self.run_script(f'{self.id}.series.setData([])') |
@@ -594,6 +609,47 @@ def set(self, df: Optional[pd.DataFrame] = None, keep_drawings=False): |
594 | 609 | else: |
595 | 610 | self.run_script(f"{self._chart.id}.toolBox?.clearDrawings()") |
596 | 611 |
|
| 612 | + def set_zipped(self, df: Optional[pd.DataFrame] = None, keep_drawings=False): |
| 613 | + """ |
| 614 | + Sets the initial data for the chart.\n |
| 615 | + :param df: columns: date/time, open, high, low, close, volume (if volume enabled). |
| 616 | + :param keep_drawings: keeps any drawings made through the toolbox. Otherwise, they will be deleted. |
| 617 | + """ |
| 618 | + if df is None or df.empty: |
| 619 | + self.run_script(f'{self.id}.series.setData([])') |
| 620 | + self.run_script(f'{self.id}.volumeSeries.setData([])') |
| 621 | + self.candle_data = pd.DataFrame() |
| 622 | + return |
| 623 | + df = self._df_datetime_format(df) |
| 624 | + df_copy = df.copy() |
| 625 | + self.candle_data = df_copy[['time', 'open', 'high', 'low', 'close']] |
| 626 | + self._last_bar = df.iloc[-1] |
| 627 | + candle_js_data = js_zipdata(df[['time', 'open', 'high', 'low', 'close']]) |
| 628 | + self.run_script(f'{self.id}.series.setData(await decodeGzJSON("{candle_js_data}"))') |
| 629 | + |
| 630 | + if 'volume' not in df: |
| 631 | + return |
| 632 | + volume = df[['time', 'volume']].rename(columns={'volume': 'value'}) |
| 633 | + volume['color'] = self._volume_down_color |
| 634 | + volume.loc[df['close'] > df['open'], 'color'] = self._volume_up_color |
| 635 | + volume_js_data = js_zipdata(volume) |
| 636 | + self.run_script(f'{self.id}.volumeSeries.setData(await decodeGzJSON("{volume_js_data}"))') |
| 637 | + |
| 638 | + for line in self._lines: |
| 639 | + if line.name not in df.columns: |
| 640 | + continue |
| 641 | + line.set(df[['time', line.name]], format_cols=False) |
| 642 | + # set autoScale to true in case the user has dragged the price scale |
| 643 | + self.run_script(f''' |
| 644 | + if (!{self.id}.chart.priceScale("right").options.autoScale) |
| 645 | + {self.id}.chart.priceScale("right").applyOptions({{autoScale: true}}) |
| 646 | + ''') |
| 647 | + # TODO keep drawings doesn't work consistenly w |
| 648 | + if keep_drawings: |
| 649 | + self.run_script(f'{self._chart.id}.toolBox?._drawingTool.repositionOnTime()') |
| 650 | + else: |
| 651 | + self.run_script(f"{self._chart.id}.toolBox?.clearDrawings()") |
| 652 | + |
597 | 653 | def update(self, series: pd.Series, _from_tick=False): |
598 | 654 | """ |
599 | 655 | Updates the data from a bar; |
|
0 commit comments