Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
<div align="center">
# lightweight-charts-python

## Installation

```bash
pip install lightweight-charts-esistjosh


## Installation
```
pip install lightweight-charts-esistjosh
```
## Forked to Add Features
![Cover Image](https://raw.githubusercontent.com/EsIstJosh/lightweight-charts-python/main/Screenshot2025-02-07114921.png)

Expand Down Expand Up @@ -133,12 +143,12 @@ For full details, refer to the [MIT License](./MIT_LICENSE).
## Installation

```bash
pip install lightweight-charts
pip install lightweight-charts-esistjosh


## Installation
```
pip install lightweight-charts
pip install lightweight-charts-esistjosh
```
___

Expand Down
14 changes: 7 additions & 7 deletions lightweight_charts_esistjosh/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -1193,7 +1193,7 @@ class AbstractChart(Candlestick, Pane):
def __init__(self, window: Window, width: float = 1.0, height: float = 1.0,
scale_candles_only: bool = False, toolbox: bool = False,
autosize: bool = True, position: FLOAT = 'left',
defaults: str = '../../src/general/defaults', scripts: str = '../../src/general/scripts'):
defaults: str = '../defaults', scripts: str = '../scripts'):
Pane.__init__(self, window)
Candlestick.__init__(self, self)
self._lines = []
Expand All @@ -1216,23 +1216,23 @@ def __init__(self, window: Window, width: float = 1.0, height: float = 1.0,
self.toolbox: ToolBox = ToolBox(self)

# Set and initialize defaults directory
self.defaults = defaults or './defaults'
self.defaults = defaults or '../defaults'
if not os.path.exists(self.defaults):
os.makedirs(self.defaults, exist_ok=True)
if os.path.exists('../../src/general/defaults'):
shutil.copytree('../../src/general/defaults', self.defaults, dirs_exist_ok=True)
if os.path.exists('../defaults'):
shutil.copytree('../defaults', self.defaults, dirs_exist_ok=True)
self.set_defaults(self.defaults)

# Handlers for defaults
self.win.handlers['save_defaults'] = self._save_defaults
self.events.save_defaults += self._save_defaults

# Set and initialize scripts directory
self.scripts = scripts or './scripts'
self.scripts = scripts or '../scripts'
if not os.path.exists(self.scripts):
os.makedirs(self.scripts, exist_ok=True)
if os.path.exists('../../src/general/scripts'):
shutil.copytree('../../src/general/scripts', self.scripts, dirs_exist_ok=True)
if os.path.exists('../scripts'):
shutil.copytree('../scripts', self.scripts, dirs_exist_ok=True)
self.set_scripts(self.scripts)

# Handlers for scripts
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions lightweight_charts_esistjosh/js/.old
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

4 changes: 2 additions & 2 deletions lightweight_charts_esistjosh/js/bundle.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions lightweight_charts_esistjosh/js/lightweight-charts.js

Large diffs are not rendered by default.

File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion run.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def on_timeframe_selection(chart):
df1 = data.iloc[:midpoint]
df2 = data.iloc[midpoint+1:]

chart = Chart(toolbox=True, debug=True)
chart = Chart(toolbox=True, debug=True, defaults= "./lightweight_charts_esistjosh/defaults", scripts= "./lightweight_charts_esistjosh/scripts")
chart.legend(True)
chart.set(df1)

Expand Down
10 changes: 8 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setup(
name='lightweight_charts_esistjosh',
version='3.0.3',
version='3.0.4',
packages=find_packages(),
python_requires='>=3.8',
install_requires=[
Expand All @@ -14,8 +14,14 @@
'pywebview>=5.0.5',
],
package_data={
'lightweight_charts_esistjosh': ['js/*'],
# “**” says “and everything under here, at any depth”
"lightweight_charts_esistjosh": [
"defaults/**/*",
"scripts/**/*",
"js/*.js",
],
},

author='EsIstJosh',
license='MIT/AGPL-3.0',
description="Python framework for TradingView's Lightweight Charts JavaScript library.",
Expand Down
2 changes: 1 addition & 1 deletion src/box/box.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export class Box extends TwoPointDrawing {
}
}

protected _mouseIsOverDrawing(param: MouseEventParams, tolerance = 4) {
protected _mouseIsOverTwoPointDrawing(param: MouseEventParams, tolerance = 4) {
if (!param.point) return false;

const x1 = this._paneViews[0]._p1.x;
Expand Down
2 changes: 1 addition & 1 deletion src/general/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -737,7 +737,7 @@ createSymbolSeries(
}

createToolBox() {
this.toolBox = new ToolBox(this, this.id, this.chart, this.series, this.commandFunctions);
this.toolBox = new ToolBox(this, this.chart, this.series, this.commandFunctions);
this.div.appendChild(this.toolBox.div);
}

Expand Down
389 changes: 197 additions & 192 deletions src/general/toolbox.ts

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions src/helpers/series.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,10 @@ import { findColorOptions } from "./colors";
import { PineTS } from "pinets";
import { convertTime, formattedDateAndTime } from "./time";
import { DefaultOptionsManager } from "../general/defaults";
import { IsExternal } from "rollup";
import { defaultSymbolSeriesOptions, SymbolSeriesOptions } from "../symbol-series/options";
import { SymbolSeries } from "../symbol-series/symbol-series";
import { tradeDefaultOptions, TradeData } from "../tx-series/renderer";
import { SymbolSeriesData } from "../symbol-series/data";
import { defaultFillAreaOptions, FillArea } from "../fill-area/fill-area";
import { base } from "acorn-walk";
export interface ISeriesApiExtended extends ISeriesApi<SeriesType> {
primitives: {
[key: string]: any; // Dictionary for attached primitives
Expand Down
157 changes: 157 additions & 0 deletions src/measure/measure.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import {
LineStyle,
MouseEventParams,
} from 'lightweight-charts';

import { Point } from '../drawing/data-source';
import { InteractionState } from '../drawing/drawing';
import { DrawingOptions, defaultOptions } from '../drawing/options';
import { MeasurePaneView } from './pane-view';
import { TwoPointDrawing } from '../drawing/two-point-drawing';


export interface MeasureOptions extends DrawingOptions {
fillEnabled: boolean;
fillColor: string;
}

const defaultBoxOptions = {
fillEnabled: true,
fillColor: 'rgba(255, 255, 255, 0.0)',

lineColor: '#1E80F0',
lineStyle: LineStyle.Solid,
width: 1,
}


export class Measure extends TwoPointDrawing {
_type = "Measure";

constructor(
p1: Point,
p2: Point,
options?: Partial<MeasureOptions>
) {
super(p1, p2, options);
this._options = {
...defaultBoxOptions,
...options,
}
this._paneViews = [new MeasurePaneView(this)];
}

// autoscaleInfo(startTimePoint: Logical, endTimePoint: Logical): AutoscaleInfo | null {
// const p1Index = this._pointIndex(this._p1);
// const p2Index = this._pointIndex(this._p2);
// if (p1Index === null || p2Index === null) return null;
// if (endTimePoint < p1Index || startTimePoint > p2Index) return null;
// return {
// priceRange: {
// minValue: this._minPrice,
// maxValue: this._maxPrice,
// },
// };
// }

_moveToState(state: InteractionState) {
switch(state) {
case InteractionState.NONE:
document.body.style.cursor = "default";
this._hovered = false;
this._unsubscribe("mousedown", this._handleMouseDownInteraction);
break;

case InteractionState.HOVERING:
document.body.style.cursor = "pointer";
this._hovered = true;
this._unsubscribe("mouseup", this._handleMouseUpInteraction);
this._subscribe("mousedown", this._handleMouseDownInteraction)
this.chart.applyOptions({handleScroll: true});
break;

case InteractionState.DRAGGINGP1:
case InteractionState.DRAGGINGP2:
case InteractionState.DRAGGINGP3:
case InteractionState.DRAGGINGP4:
case InteractionState.DRAGGING:
document.body.style.cursor = "grabbing";
document.body.addEventListener("mouseup", this._handleMouseUpInteraction);
this._subscribe("mouseup", this._handleMouseUpInteraction);
this.chart.applyOptions({handleScroll: false});
break;
}
this._state = state;
}

_onDrag(diff: any) {
if (this._state == InteractionState.DRAGGING || this._state == InteractionState.DRAGGINGP1) {
this._addDiffToPoint(this.p1, diff.logical, diff.price);
}
if (this._state == InteractionState.DRAGGING || this._state == InteractionState.DRAGGINGP2) {
this._addDiffToPoint(this.p2, diff.logical, diff.price);
}
if (this._state != InteractionState.DRAGGING) {
if (this._state == InteractionState.DRAGGINGP3) {
this._addDiffToPoint(this.p1, diff.logical, 0);
this._addDiffToPoint(this.p2, 0, diff.price);
}
if (this._state == InteractionState.DRAGGINGP4) {
this._addDiffToPoint(this.p1, 0, diff.price);
this._addDiffToPoint(this.p2, diff.logical, 0);
}
}
}

protected _onMouseDown() {
this._startDragPoint = null;
const hoverPoint = this._latestHoverPoint;
const p1 = this._paneViews[0]._p1;
const p2 = this._paneViews[0]._p2;

if (!p1.x || !p2.x || !p1.y || !p2.y) return this._moveToState(InteractionState.DRAGGING);

const tolerance = 10;
if (Math.abs(hoverPoint.x-p1.x) < tolerance && Math.abs(hoverPoint.y-p1.y) < tolerance) {
this._moveToState(InteractionState.DRAGGINGP1)
}
else if (Math.abs(hoverPoint.x-p2.x) < tolerance && Math.abs(hoverPoint.y-p2.y) < tolerance) {
this._moveToState(InteractionState.DRAGGINGP2)
}
else if (Math.abs(hoverPoint.x-p1.x) < tolerance && Math.abs(hoverPoint.y-p2.y) < tolerance) {
this._moveToState(InteractionState.DRAGGINGP3)
}
else if (Math.abs(hoverPoint.x-p2.x) < tolerance && Math.abs(hoverPoint.y-p1.y) < tolerance) {
this._moveToState(InteractionState.DRAGGINGP4)
}
else {
this._moveToState(InteractionState.DRAGGING);
}
}

protected _mouseIsOverTwoPointDrawing(param: MouseEventParams, tolerance = 4) {
if (!param.point) return false;

const x1 = this._paneViews[0]._p1.x;
const y1 = this._paneViews[0]._p1.y;
const x2 = this._paneViews[0]._p2.x;
const y2 = this._paneViews[0]._p2.y;
if (!x1 || !x2 || !y1 || !y2 ) return false;

const mouseX = param.point.x;
const mouseY = param.point.y;

const mainX = Math.min(x1, x2);
const mainY = Math.min(y1, y2);

const width = Math.abs(x1-x2);
const height = Math.abs(y1-y2);

const halfTolerance = tolerance/2;

return mouseX > mainX-halfTolerance && mouseX < mainX+width+halfTolerance &&
mouseY > mainY-halfTolerance && mouseY < mainY+height+halfTolerance;
}
}


Loading
Loading