23. 2. 2026

5 4

Rename Strategies with Batch Find & Replace – Custom Analysis

Ideal if you want to quickly create clean, informative names across a whole databank – this Custom Analysis snippet lets you batch rename strategies in StrategyQuant X using simple find → replace (or just find → remove).

What it does

  • Runs as a Custom Analysis (Full databank analysis).

  • Input args accepts find=>replace or just find to remove.

  • Renames in place in the selected Source databank.

  • Literal, case-sensitive match. Supports \n, \t, \r.

  • Great for mass cleaning: trim prefixes/suffixes, remove words, standardize symbols/timeframes/directions.

How to install

  1. Code Editor → New → Custom Analysis, name the file CARenameFindReplace
  2. Paste the code (below) and Compile.
  3. If needed, restart SQX.

How to use

  1. Custom Project → Task → Custom Analysis. (Can also be run inside a databank from Databank > Tools > Run CA).
  2. In Full databank analysis, select CARenameFindReplace and choose your Source databank.
  3. In Input args enter one of:
    -
    Replace: old=>new
    Remove: old
    -
  4. Enable 'Filter by results of custom analysis' to rename the original strategies. (If you disable this, the strategies will be duplicated and only the duplicates renamed, leaving the originals untouched.)
  5. Run. All strategy names in the Source databank are updated.

Examples

  • Remove the word “Strategy ” (with trailing space):
    Strategy =>
  • Convert SQX auto-name to a formatted label:
    Strategy =>XAUUSD_H1_L_
  • Strip dots after a prefix pass:
    .=>

Tip: Run multiple passes for multi-step formatting (e.g., add a prefix, then strip characters, then add a suffix). Consider duplicating the databank first if you want an easy rollback.

Code:

package SQ.CustomAnalysis;

import com.strategyquant.tradinglib.*;
import com.strategyquant.tradinglib.project.ProjectEngine;
import com.strategyquant.tradinglib.project.SQProject;

import java.util.ArrayList;
import java.util.HashSet;

public class CARenameFindReplace extends CustomAnalysisMethod {

    public CARenameFindReplace() {
        super("CARenameFindReplace", TYPE_PROCESS_DATABANK);
    }

    @Override
    public boolean filterStrategy(String project, String task, String databankName, ResultsGroup rg) throws Exception {
        return true;
    }

    @Override
    public ArrayList processDatabank(
            String project,
            String task,
            String databankName,
            ArrayList databankRG) throws Exception {

        // Read single Input args string
        String raw = getInputArgs();
        if (raw == null) raw = "";
        raw = raw.trim();

        // No args -> do nothing
        if (raw.isEmpty()) {
            return databankRG;
        }

        // Parse: "find=>replace" OR just "find" (remove)
        String find, repl;
        int arrow = raw.indexOf("=>");
        if (arrow >= 0) {
            find = raw.substring(0, arrow);
            repl = raw.substring(arrow + 2);
        } else {
            find = raw;
            repl = "";
        }

        find = unescape(find);
        repl = unescape(repl);

        // If find is empty, do nothing (prevents accidental rename-all)
        if (find.isEmpty()) {
            return databankRG;
        }

        SQProject prj = ProjectEngine.get(project);
        Databank db = prj.getDatabanks().get(databankName);

        // Snapshot of originals to avoid ConcurrentModificationException
        ArrayList snapshot = new ArrayList<>(databankRG);

        // Track existing names so we can avoid collisions if needed
        HashSet usedNames = new HashSet<>();
        for (ResultsGroup rg : snapshot) {
            if (rg.getName() != null) usedNames.add(rg.getName());
        }

        // 1) Create renamed clones (no db.add inside the iteration)
        ArrayList clonesToAdd = new ArrayList<>();

        for (ResultsGroup rg : snapshot) {
            String oldName = rg.getName();
            if (oldName == null) continue;

            String newName = oldName.replace(find, repl);

            // Only duplicate if name changes
            if (!newName.equals(oldName)) {
                // Avoid exact-name collisions (optional safety)
                String finalName = makeUniqueName(newName, usedNames);

                ResultsGroup newRg = rg.clone();
                newRg.setName(finalName);

                clonesToAdd.add(newRg);
                usedNames.add(finalName);
            }
        }

        // 2) Add clones after iteration (safe)
        for (ResultsGroup newRg : clonesToAdd) {
            db.add(newRg, true);
        }

        // Return the newly created strategies (mirrors SQX RenameStrategies behaviour)
        return clonesToAdd;
    }

    private static String makeUniqueName(String baseName, HashSet used) {
        if (!used.contains(baseName)) return baseName;

        int i = 2;
        while (true) {
            String candidate = baseName + "_" + i;
            if (!used.contains(candidate)) return candidate;
            i++;
        }
    }

    private static String unescape(String s) {
        if (s == null) return "";
        return s.replace("\\n", "\n")
                .replace("\\t", "\t")
                .replace("\\r", "\r");
    }
}

 

4 Comments
Oldest
Newest Most Voted
Vincent Orain
13. 5. 2026 9:20 pm

Hi
Compilation failed for me. 3 errors
Maybe version 144

Related posts