pinets-cli 0.1.0 → 0.1.1

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/README.md CHANGED
@@ -39,6 +39,12 @@ No code to write. No project to set up. Just point it at a `.pine` file and go.
39
39
  npm install -g pinets-cli
40
40
  ```
41
41
 
42
+ Or run directly without installing:
43
+
44
+ ```bash
45
+ npx pinets-cli run sma_cross.pine --symbol BTCUSDT --timeframe 60
46
+ ```
47
+
42
48
  ### Run your first indicator
43
49
 
44
50
  Create a file called `sma_cross.pine`:
@@ -113,6 +119,8 @@ pinets run rsi.pine --data ./my_candles.json
113
119
  | `--output <path>` | `-o` | Write output to a file instead of stdout | stdout |
114
120
  | `--format <type>` | `-f` | Output format: `default` or `full` | `default` |
115
121
  | `--pretty` | &mdash; | Force pretty-printed JSON | auto |
122
+ | `--clean` | &mdash; | Filter out null, false, and empty values from plots | &mdash; |
123
+ | `--plots <names>` | &mdash; | Comma-separated list of plot names to include | all plots |
116
124
 
117
125
  ### Candle Control
118
126
 
@@ -192,6 +200,30 @@ pinets run rsi.pine --symbol BTCUSDT --format full --pretty
192
200
  pinets run my_indicator.pine --symbol BTCUSDT --debug
193
201
  ```
194
202
 
203
+ ### Filter signals with --clean
204
+
205
+ For indicators that generate signals (like crossovers), most candles will have `false` values. Use `--clean` to filter them out:
206
+
207
+ ```bash
208
+ # Without --clean: 500 entries, mostly false
209
+ pinets run ma_cross.pine -s BTCUSDT -t 1D -n 500
210
+
211
+ # With --clean: Only actual signals
212
+ pinets run ma_cross.pine -s BTCUSDT -t 1D -n 500 --clean
213
+ ```
214
+
215
+ ### Select specific plots
216
+
217
+ When you only need specific plots from an indicator:
218
+
219
+ ```bash
220
+ # Get only the Fast SMA (ignore Slow SMA)
221
+ pinets run sma_cross.pine -s BTCUSDT --plots "Fast SMA"
222
+
223
+ # Get only Buy and Sell signals
224
+ pinets run signals.pine -s BTCUSDT --plots "Buy,Sell" --clean -q | jq '.plots'
225
+ ```
226
+
195
227
  ---
196
228
 
197
229
  ## Output Formats
@@ -4501,13 +4501,13 @@ function readStdin(timeoutMs = 1e4) {
4501
4501
  });
4502
4502
  }
4503
4503
 
4504
- function formatOutput(context, format, candles) {
4504
+ function formatOutput(context, format, candles, clean, plotFilter) {
4505
4505
  switch (format) {
4506
4506
  case "full":
4507
- return formatFull(context, candles);
4507
+ return formatFull(context, candles, clean, plotFilter);
4508
4508
  case "default":
4509
4509
  default:
4510
- return formatDefault(context, candles);
4510
+ return formatDefault(context, candles, clean, plotFilter);
4511
4511
  }
4512
4512
  }
4513
4513
  function writeOutput(data, outputPath, pretty, quiet) {
@@ -4523,14 +4523,25 @@ function writeOutput(data, outputPath, pretty, quiet) {
4523
4523
  process.stdout.write(json + "\n");
4524
4524
  }
4525
4525
  }
4526
- function formatDefault(context, candles) {
4526
+ function formatDefault(context, candles, clean, plotFilter) {
4527
4527
  const plots = {};
4528
+ const includePlots = plotFilter ? new Set(plotFilter.split(",").map((s) => s.trim()).filter((s) => s.length > 0)) : null;
4528
4529
  for (const [title, plotData] of Object.entries(context.plots)) {
4529
- const data = plotData.data;
4530
+ if (includePlots && !includePlots.has(title)) {
4531
+ continue;
4532
+ }
4533
+ let data = plotData.data;
4534
+ data = data.length > candles ? data.slice(-candles) : data;
4535
+ if (clean) {
4536
+ data = data.filter((entry) => {
4537
+ const val = entry.value;
4538
+ return val !== null && val !== false && val !== void 0 && val !== "";
4539
+ });
4540
+ }
4530
4541
  plots[title] = {
4531
4542
  title: plotData.title,
4532
4543
  options: plotData.options,
4533
- data: data.length > candles ? data.slice(-candles) : data
4544
+ data
4534
4545
  };
4535
4546
  }
4536
4547
  return {
@@ -4538,8 +4549,8 @@ function formatDefault(context, candles) {
4538
4549
  plots
4539
4550
  };
4540
4551
  }
4541
- function formatFull(context, candles) {
4542
- const defaultOutput = formatDefault(context, candles);
4552
+ function formatFull(context, candles, clean, plotFilter) {
4553
+ const defaultOutput = formatDefault(context, candles, clean, plotFilter);
4543
4554
  const md = context.marketData;
4544
4555
  const trimmedMarketData = md.length > candles ? md.slice(-candles) : md;
4545
4556
  let result = context.result;
@@ -4654,7 +4665,7 @@ async function runCommand(file, options) {
4654
4665
  log(quiet, "Executing...");
4655
4666
  const context = await pineTS.run(indicatorCode);
4656
4667
  log(quiet, "Done.");
4657
- const output = formatOutput(context, options.format, candles);
4668
+ const output = formatOutput(context, options.format, candles, options.clean, options.plots);
4658
4669
  const pretty = options.pretty !== void 0 ? true : options.output ? false : !!process.stdout.isTTY;
4659
4670
  writeOutput(output, options.output, pretty, quiet);
4660
4671
  } catch (err) {
@@ -4696,7 +4707,7 @@ const PACKAGE_NAME = "pinets-cli";
4696
4707
  async function main() {
4697
4708
  const updateCheck = checkForUpdate(VERSION, PACKAGE_NAME);
4698
4709
  program.name("pinets").description("CLI for running Pine Script indicators via PineTS").version(VERSION, "-v, --version");
4699
- program.command("run").description("Execute a Pine Script indicator").argument("[file]", "Path to indicator file (.pine or any text file)").option("-s, --symbol <ticker>", "Symbol to query (e.g., BTCUSDT, ETHUSDT.P)").option("-t, --timeframe <tf>", "Timeframe: 1, 5, 15, 60, 240, 1D, 1W, 1M", "60").option("-d, --data <path>", "Path to JSON data file (alternative to --symbol)").option("-o, --output <path>", "Write output to file (default: stdout)").option("-f, --format <type>", "Output format: default | full", "default").option("--pretty", "Pretty-print JSON output").option("-n, --candles <count>", "Number of output candles", "500").option("-w, --warmup <count>", "Extra warmup candles for indicator init", "0").option("--debug", "Show transpiled code").option("-q, --quiet", "Suppress informational messages").action(runCommand);
4710
+ program.command("run").description("Execute a Pine Script indicator").argument("[file]", "Path to indicator file (.pine or any text file)").option("-s, --symbol <ticker>", "Symbol to query (e.g., BTCUSDT, ETHUSDT.P)").option("-t, --timeframe <tf>", "Timeframe: 1, 5, 15, 60, 240, 1D, 1W, 1M", "60").option("-d, --data <path>", "Path to JSON data file (alternative to --symbol)").option("-o, --output <path>", "Write output to file (default: stdout)").option("-f, --format <type>", "Output format: default | full", "default").option("--pretty", "Pretty-print JSON output").option("--clean", "Filter out null, false, and empty values from plot data").option("--plots <names>", "Comma-separated list of plot names to include").option("-n, --candles <count>", "Number of output candles", "500").option("-w, --warmup <count>", "Extra warmup candles for indicator init", "0").option("--debug", "Show transpiled code").option("-q, --quiet", "Suppress informational messages").action(runCommand);
4700
4711
  await program.parseAsync();
4701
4712
  const notice = await Promise.race([
4702
4713
  updateCheck,