Skip to content
Closed
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
2 changes: 2 additions & 0 deletions .github/workflows/cd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ on:
description: "Triplet to build (linux-x64-gnu / win32-x64-msvc)"
required: false
type: string

# on:
# pull_request:
# push:
# branches:
# - master

# workflow_run:
# workflows: ["CI"]
# types: [completed]
Expand Down
18 changes: 15 additions & 3 deletions algoalpha/.qpace.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,22 @@
"install": false,
"test": false,
"py": {
"package": "algoalpha"
"package": {
"name": "algoalpha",
"version": "0.0.1"
}
},
"js": {
"package": "algoalpha"
"package": {
"name": "algoalpha",
"version": "0.0.1"
}
},
"include": ["supertrended_rsi.pine"]
"include": [
"adaptive_schaff_trend_cycle.pine",
"amazing_oscillator.pine",
"exponential_trend.pine",
"supertrended_rsi.pine",
"triple_smoothed_signals.pine"
]
}
12 changes: 12 additions & 0 deletions algoalpha/BUILD.bazed
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
fileSet("pine", {
srcs: [".qpace_json", glob("*.pine")],
});

tsLibrary("src", {
srcs: ["build.ts"],
});

nodeEntry("algoalpha", {
main: "build.js",
deps: ["//base/node", ":src", ":pine"],
});
77 changes: 77 additions & 0 deletions algoalpha/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# AlgoAlpha x QPACE

QPACE:

- [Website](https://qpace.dev)
- [Documentation](/DOCS.md)

AlgoAlpha:

- [Website](https://www.algoalpha.io/)

## Indicators

- [Adaptive Schaff Trend Cycle (STC)](https://www.tradingview.com/v/yOxili7R/)
- [Amazing Oscillator (AO)](https://www.tradingview.com/v/g9j9piQE/)
- [Exponential Trend](https://www.tradingview.com/v/CDb3oR6A/)
- [Supertrended RSI](https://www.tradingview.com/v/tjP35RG5/)
- [Triple Smoothed Signals](https://www.tradingview.com/v/FoMINXVf/)

## Python

```bash
pip install qpace algoalpha
```

```python
import qpace as qp
import algoalpha as aa

ohlcv = qp.Ohlcv.read_csv("btc_csv", qp.Timeframe.Days(1))
ctx = qp.Ctx(ohlcv, qp.Sym.BTC_USD())

res = aa.supertrended_rsi.main(ctx.copy())
print(res["locals"]["rsi_value"][0:30])
```

## JavaScript

```bash
npm add qpace algoalpha
```

Node.js:

```ts
import * as qp from "qpace/node";
import * as aa from "algoalpha/node";

const ohlcv = qp.Ohlcv.readCsv("btc_csv", qp.Timeframe.Days(1))
const ctx = qp.Ctx(ohlcv, qp.BTC_USD())

const res = aa.supertrended_rsi.main(ctx.copy())
console.log(res.locals.rsi_value.slice(0, 30))
```

Browser:

```ts
import * as qp from "qpace/web";
import * as aa from "algoalpha/web";

window.onload = async () => {
// Initialize WASM Modules
{
await qp.init();
await qp.ta.init();
await aa.init();
}

const ohlcv = qp.Ohlcv.fromBars([ ... ])
const ctx = qp.Ctx(ohlcv, qp.BTC_USD())

const res = aa.supertrended_rsi.main(ctx.copy())
console.log(res.locals.rsi_value.slice(0, 30))
}

```
4 changes: 2 additions & 2 deletions algoalpha/amazing_oscillator.pine
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ rise = ta.rma(math.max(ta.change(amazingOsc), 0), oscPeriod)
fall = ta.rma(-math.min(ta.change(amazingOsc), 0), oscPeriod)
customRSI = (fall == 0 ? 100 : rise == 0 ? 0 : 100 - (100 / (1 + rise / fall))) - 50
opacityLevel = customRSI > 0 and customRSI > customRSI[1] or customRSI < 0 and customRSI < customRSI[1] ? 30 : 80
barColor = customRSI > 0 ? color.new(upColor, opacityLevel) : color.new(downColor, opacityLevel)
// barColor = customRSI > 0 ? color.new(upColor, opacityLevel) : color.new(downColor, opacityLevel)

// --------------------- EXPORTED ---------------------
var float custom_rsi = na
stc := customRSI
custom_rsi := customRSI
// ----------------------------------------------------

// Plots
Expand Down
52 changes: 52 additions & 0 deletions algoalpha/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import chalk from "chalk";
import { mkdir } from "fs/promises";
import { resolve } from "path";
import { exec } from "~/base/node/exec";
import { clearDir } from "~/base/node/fs";
import { BuildTarget } from "~/cli/compiler";

const WORKSPACE_PATH = process.env["BAZED_WORKSPACE_ROOT"] ?? process.cwd();

const main = async (): Promise<void> => {
const root = resolve(WORKSPACE_PATH, "algoalpha");
const baseCommand = "pnpm bazed run //cli:main --verbose --";
await exec({
command: `${baseCommand} --version`,
io: true,
});
const outDir = resolve(WORKSPACE_PATH, "out/algoalpha");
console.log(chalk.magentaBright(outDir));
await clearDir(outDir);
await mkdir(outDir, { recursive: true });

const targets: BuildTarget[] = [
"python-x86_64-windows",
"python-x86_64-macos",
"python-x86_64-linux",
"python-arm64-macos",
"python-arm64-linux",
"js",
//
// "wasm-unknown-unknown",
// "node-x86_64-windows",
// "node-x86_64-linux",
// "node-x86_64-macos",
// "node-arm64-linux",
// "node-arm64-macos",
];

for (const target of targets) {
await exec({
command: `${baseCommand} build --target ${target} --out-dir ${outDir} --verbose --cwd ${root}`,
verbose: true,
cwd: root,
throw: true,
env: {
...process.env,
// DEV: true,
},
});
}
};

main();
4 changes: 2 additions & 2 deletions algoalpha/supertrended_rsi.pine
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ smoothingLength = input.int(21, title="RSI Smoothing Length", group="RSI Setting
rsiInputSource = input.source(close, title="RSI Source", group="RSI Settings")
isSmoothed = input.bool(false, "Smooth RSI?", group="RSI Settings")

movingAverageLength = input.int(14, title="MA Length", group="MA Settings", display = display.data_window)
movingAverageType = input.string("HMA", title="MA Type", options=["SMA", "HMA", "EMA", "SMMA (RMA)", "WMA", "VWMA"], group="MA Settings", display = display.data_window)
movingAverageLength = input.int(14, title="MA Length", group="MA Settings") // , display = display.data_window
movingAverageType = input.string("HMA", title="MA Type", options=["SMA", "HMA", "EMA", "SMMA (RMA)", "WMA", "VWMA"], group="MA Settings") // , display = display.data_window
// showMovingAverage = input.bool(true, "Show RSI MA?", group="MA Settings")

trendFactor = input.float(0.8, title="Factor", group="Super Trend Settings")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ ma(source, length, MAtype) =>
"RMA" => ta.rma(source, length)
"WMA" => ta.wma(source, length)

var float m1 = na
var float m2 = na
var float v1 = na
var float v2 = na
var float dist = na
var float ndist = na
var float h = na
Expand Down
124 changes: 65 additions & 59 deletions base/node/exec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export interface ExecOptions {
returnChild?: boolean;
detached?: boolean;
verbose?: boolean;
throw?: boolean;
}

export interface ExecResult {
Expand Down Expand Up @@ -54,7 +55,7 @@ export async function exec(options: ExecOptions): Promise<ExecResult> {
const req = {
command: commandStr,
args: args ?? [],
env: options.env ?? process.env,
env: options.env ?? {},
shell: options.shell ?? true,
cwd: options.cwd ?? undefined,
stdio:
Expand All @@ -66,70 +67,75 @@ export async function exec(options: ExecOptions): Promise<ExecResult> {
returnChild: options.returnChild,
};

const execRes = await new Promise<ExecResult>((resolvePromise) => {
const env = req.env;
const cwd = req.cwd != null ? resolve(req.cwd) : undefined;
const execRes = await new Promise<ExecResult>(
(resolvePromise, rejectPromise) => {
const env = req.env;
const cwd = req.cwd != null ? resolve(req.cwd) : undefined;

if (tmpScriptPath) {
commandStr = `bash "${tmpScriptPath}"`;
}

const child = spawn(commandStr, req.args, {
env,
shell: req.shell,
cwd,
stdio: req.stdio as any,
detached: options.detached,
});

if (req.returnChild) {
return resolvePromise(child as any);
}

let stdout = "";
const stderr = "";

let exitCode: number | null = null;
let signal: NodeJS.Signals | null = null;
let killTimer: NodeJS.Timeout | undefined;
if (tmpScriptPath) {
commandStr = `bash "${tmpScriptPath}"`;
}

let alreadyFinished = false;
const child = spawn(commandStr, req.args, {
env,
shell: req.shell,
cwd,
stdio: req.stdio as any,
detached: options.detached,
});

const finish = (): void => {
if (alreadyFinished) {
throw new Error("Already finished. This should not happen");
if (req.returnChild) {
return resolvePromise(child as any);
}
alreadyFinished = true;
clearTimeout(killTimer);
const res: ExecResult = {
stdout,
stderr,
command: commandStr,
exitCode: exitCode ?? 0,
signal: signal ?? undefined,

let stdout = "";
const stderr = "";

let exitCode: number | null = null;
let signal: NodeJS.Signals | null = null;
let killTimer: NodeJS.Timeout | undefined;

let alreadyFinished = false;

const finish = (): void => {
if (alreadyFinished) {
throw new Error("Already finished. This should not happen");
}
alreadyFinished = true;
clearTimeout(killTimer);
const res: ExecResult = {
stdout,
stderr,
command: commandStr,
exitCode: exitCode ?? 0,
signal: signal ?? undefined,
};
if (exitCode !== 0 && options.throw) {
return rejectPromise(res);
}
resolvePromise(res);
};
resolvePromise(res);
};

child.stdout?.on("data", (data) => {
stdout += data;
if (options.verbose) {
process.stdout.write(data);
}
});
child.stderr?.on("data", (data) => {
stdout += data;
if (options.verbose) {
process.stderr.write(data);
}
});

child.on("exit", (_exitCode, _signal) => {
exitCode = _exitCode;
signal = _signal;
finish();
});
});
child.stdout?.on("data", (data) => {
stdout += data;
if (options.verbose) {
process.stdout.write(data);
}
});
child.stderr?.on("data", (data) => {
stdout += data;
if (options.verbose) {
process.stderr.write(data);
}
});

child.on("exit", (_exitCode, _signal) => {
exitCode = _exitCode;
signal = _signal;
finish();
});
},
);
execRes.command = req.command;

return execRes;
Expand Down
Loading