Skip to content

~(Root)

[ SECTOR: LOGIC_ENGINE ]

> STATUS: Manual Narrative currently active. EA automation in development.

> CORE_ENGINE: ratsCode is a laboratory for quantitative retail trading systems. Specializing in formalization of Chan Theory (纏論 Stroke/ Center logic) and Volume Profile reference.

> OBJECTIVE: Exploring if consistent edge comes from removing "Psychological Interference" error. Trading tiny to perform big. View assembly of every trade in [03_LOGS].

> DISCLAIMER: Not investment advice. Trading risks capital loss. Past performance no guarantee. Unlicensed under SFC.

~(Result)

> CAPITAL_AT_RISK: All trading strategies carry risk. Performance audited by Myfxbook. Past performance is not an indicator of future success. Unlicensed under SFC/Financial Authorities.

> RECORD: Track my trading history using MyFXBook or the Vantage platform.  Please note there is a slight synchronization delay with the MyFXBook record. For the most up-to-date performance data, please refer directly to the Vantage Markets platform.

[ AUDIT: PERFORMANCE_REPORT ] ● VERIFIED_DATA_STREAM
widget

> SYSTEM_ID: ratsCode_Alpha_1

> EXECUTION_LOGIC: Chan Theory (Strokes/Centers) + Volume Profile Reference

> AUDITOR: Myfxbook Verified (Real-Time MT5 Handshake)

[ ! ] EDUCATIONAL_NOTICE: Results are shared as a live case study in systematic manual trading. This is not financial advice. Capital is at risk.

~(Logs)

> LOG_PURPOSE: These recordings serve as a manual trade journal for the development of future algorithmic systems. We document logic, error, and execution for educational transparency only.

 

~(Tools)

> TOOL_DISCLAIMER: This script is a back-testing utility for structural analysis. It is not a financial advisory tool. Users must verify logic on sandbox before live execution.

[ REPOSITORY: Pine Script V6 STROKE(Bi) V.11 ] ● PINE_SCRIPT_V6
// @version=6
// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © ratsCode

// TWINE THEORY (CHAN LUN)
// Here is a simplified introduction to its structural formation
// Inclusion: handling bars that are inside previous bars
// I. Fractals (Fen Xing - 分型):
//      The atomic unit. It requires at least 3 candlesticks.
//      Top Fractal: The middle candle has the highest High and highest Low (looks like an ^).
//      Bottom Fractal: The middle candle has the lowest High and lowest Low (looks like a v).
// II. Stroke (Bi - 筆):
//      A line connecting a Top Fractal to a Bottom Fractal (or vice versa).
//      Rule: There must be at least one independent candle between the two fractals. This filters out market noise.
// III. Line Segment (Xian Duan - 線段):
//      Formed by at least three overlapping Strokes. This shows a more significant directional move.
// IV. The Center / Pivot (Zhong Shu - 中樞):
//      The Core Concept. A Center is formed by the overlapping area of at least three consecutive Line Segments.
//      Think of this as a Consolidation Zone or a "Battlefield" where buyers and sellers are fighting.
// V. Trend: A trend is defined by the creation of two non-overlapping Centers in the same direction.

//@version=6
indicator("STROKE(Bi) V.11", shorttitle = "STROKE", overlay=true, max_boxes_count=500, max_lines_count=500, max_labels_count=500)

// ==========================================
// 0. Inputs
// ==========================================
start_bar_idx = input.int(0, "Start Calculation from Bar Index", minval=0)

// ==========================================
// 1. Structure Definition
// ==========================================
type StdBar
    float h      
    float l      
    int   idx    
    int   time   
    int   dir    

type Fractal
    float price  
    float h      
    float l      
    int   idx    
    int   time   
    int   type   // 1 = Top, -1 = Bottom
    float l_limit 
    float r_limit 

// ==========================================
// 2. State Variables
// ==========================================
var array bars = array.new()
var bool initiated = false          

// Phase A Variables
var Fractal potential_top = na      
var Fractal potential_btm = na      

// Phase B Variables
var Fractal bi_start = na           
var Fractal bi_candidate = na       
var int bi_dir = 0                  
var line current_line = na          

// ==========================================
// 3. Inclusion Logic
// ==========================================
float raw_h = high
float raw_l = low
int   raw_i = bar_index
int   raw_t = time

bool included_now = false
float plot_h = na
float plot_l = na
color plot_color = na

if bars.size() == 0
    bars.push(StdBar.new(raw_h, raw_l, raw_i, raw_t, 1))
else
    StdBar prev = bars.get(bars.size() - 1)
    bool is_included = (raw_h <= prev.h and raw_l >= prev.l) or (raw_h >= prev.h and raw_l <= prev.l)
    
    if is_included
        included_now := true
        float new_h = 0.0
        float new_l = 0.0
        
        if prev.dir == 1 
            new_h := math.max(raw_h, prev.h)
            new_l := math.max(raw_l, prev.l)
            plot_color := color.fuchsia
        else
            new_h := math.min(raw_h, prev.h)
            new_l := math.min(raw_l, prev.l)
            plot_color := color.aqua
            
        prev.h := new_h
        prev.l := new_l
        prev.idx := raw_i
        prev.time := raw_t
        plot_h := new_h
        plot_l := new_l
    else
        int new_dir = 0
        if raw_h > prev.h
            new_dir := 1
        else if raw_l < prev.l
            new_dir := -1
        else
            new_dir := prev.dir
        bars.push(StdBar.new(raw_h, raw_l, raw_i, raw_t, new_dir))

// Visuals for Inclusion (Yellow X and Box)
plotshape(included_now, title="Inclusion", style=shape.xcross, location=location.abovebar, color=color.yellow, size=size.tiny)
if included_now and bar_index > 3
    int gap1 = time[1] - time[2]
    int gap2 = time[2] - time[3]
    int duration = math.min(gap1, gap2)
    int center_time = int(time[1] + (duration / 2))
    int half_width = int(duration * 0.5)
    box.new(left = center_time - half_width, top = plot_h, right = center_time + half_width, bottom = plot_l, xloc = xloc.bar_time, border_color = plot_color, border_width = 1, bgcolor = color.new(color.white, 100))

// ==========================================
// 4. Fractal Recognition
// ==========================================
if bars.size() >= 3 and bar_index >= start_bar_idx
    
    StdBar b1 = bars.get(bars.size() - 3) // Left
    StdBar b2 = bars.get(bars.size() - 2) // Middle (Pivot)
    StdBar b3 = bars.get(bars.size() - 1) // Right
    
    bool is_top = b2.h > b1.h and b2.h > b3.h
    bool is_btm = b2.l < b1.l and b2.l < b3.l
    
    Fractal current_frac = na

    // --- FIX 1: Precise Fractal Visuals using Labels ---
    // We use labels to pin exactly to the StdBar's time and price.
    // This solves the "visual mismatch" caused by inclusion bars.
    if is_top
        current_frac := Fractal.new(b2.h, b2.h, b2.l, b2.idx, b2.time, 1, b1.l, b3.l)
        label.new(b2.time, b2.h, text="▼", xloc=xloc.bar_time, color=color.new(#4caf4f, 50), style=label.style_label_down, textcolor=color.green, size=size.tiny)
    
    if is_btm
        current_frac := Fractal.new(b2.l, b2.h, b2.l, b2.idx, b2.time, -1, b1.h, b3.h)
        label.new(b2.time, b2.l, text="▲", xloc=xloc.bar_time, color=color.new(#ff5252, 50), style=label.style_label_up, textcolor=color.red, size=size.tiny)

    // ==========================================
    // 5. Core Logic
    // ==========================================
    
    if not na(current_frac)
        
        // --------------------------------------
        // PHASE A: INITIALIZATION
        // --------------------------------------
        if not initiated
            
            if current_frac.type == 1 
                if na(potential_top) or current_frac.h >= potential_top.h
                    potential_top := current_frac
            else 
                if na(potential_btm) or current_frac.l <= potential_btm.l
                    potential_btm := current_frac

            if not na(potential_top) and not na(potential_btm)
                
                // Case A: Down Stroke
                bool time_down = potential_top.idx < potential_btm.idx
                bool dist_down = (potential_btm.idx - potential_top.idx) >= 5
                bool gap_down = potential_top.r_limit > potential_btm.l_limit 
                
                if time_down and dist_down and gap_down
                    bi_start := potential_top
                    bi_candidate := potential_btm
                    bi_dir := -1
                    initiated := true
                    current_line := line.new(bi_start.time, bi_start.price, bi_candidate.time, bi_candidate.price, xloc=xloc.bar_time, color=color.white, width=2)
                    label.new(bi_start.time, bi_start.price, "START", xloc=xloc.bar_time, color=color.yellow, style=label.style_label_left, textcolor=color.black, size=size.small)

                // Case B: Up Stroke
                bool time_up = potential_btm.idx < potential_top.idx
                bool dist_up = (potential_top.idx - potential_btm.idx) >= 5
                bool gap_up = potential_btm.r_limit < potential_top.l_limit

                if not initiated and time_up and dist_up and gap_up
                    bi_start := potential_btm
                    bi_candidate := potential_top
                    bi_dir := 1
                    initiated := true
                    current_line := line.new(bi_start.time, bi_start.price, bi_candidate.time, bi_candidate.price, xloc=xloc.bar_time, color=color.white, width=2)
                    label.new(bi_start.time, bi_start.price, "START", xloc=xloc.bar_time, color=color.yellow, style=label.style_label_left, textcolor=color.black, size=size.small)

        // --------------------------------------
        // PHASE B: RUNNING
        // --------------------------------------
        else
            // --- SCENARIO 1: Current Stroke is DOWN ---
            if bi_dir == -1
                
                // Extension
                if current_frac.type == -1 and current_frac.l < bi_candidate.l
                    bi_candidate := current_frac
                    // FIX 2: Immediate Update
                    line.set_xy2(current_line, bi_candidate.time, bi_candidate.price)
                
                // Confirmation
                else if current_frac.type == 1
                    bool dist_ok = (current_frac.idx - bi_candidate.idx) >= 5
                    bool price_ok = current_frac.h > bi_candidate.l
                    bool gap_ok = bi_candidate.r_limit < current_frac.l_limit
                    
                    if dist_ok and price_ok and gap_ok
                        bi_start := bi_candidate
                        bi_candidate := current_frac
                        bi_dir := 1 
                        current_line := line.new(bi_start.time, bi_start.price, bi_candidate.time, bi_candidate.price, xloc=xloc.bar_time, color=color.white, width=1)

            // --- SCENARIO 2: Current Stroke is UP ---
            else if bi_dir == 1
                
                // Extension
                if current_frac.type == 1 and current_frac.h > bi_candidate.h
                    bi_candidate := current_frac
                    // FIX 2: Immediate Update
                    line.set_xy2(current_line, bi_candidate.time, bi_candidate.price)
                
                // Confirmation
                else if current_frac.type == -1
                    bool dist_ok = (current_frac.idx - bi_candidate.idx) >= 5
                    bool price_ok = current_frac.l < bi_candidate.h
                    bool gap_ok = bi_candidate.r_limit > current_frac.l_limit
                    
                    if dist_ok and price_ok and gap_ok
                        bi_start := bi_candidate
                        bi_candidate := current_frac
                        bi_dir := -1 
                        current_line := line.new(bi_start.time, bi_start.price, bi_candidate.time, bi_candidate.price, xloc=xloc.bar_time, color=color.white, width=1)

// ==========================================
// 6. Real-time Visualization (The "Ghost" Line)
// ==========================================
// This ensures that even if the K-line (candle) has not closed, or the fractal has not been confirmed yet,
// we can still see the line being extended if the price has already broken through
if initiated and barstate.islast
    // If the current price is more extreme than the Candidate, we can draw a temporary dashed line or directly update the solid line.
    // Here, we choose the most robust method: only update the solid line when the fractal is confirmed.
    // However, if you want the line to appear as if it is "real-time" following the lowest point of every K-line (even without a fractal):
    
    // Note: The line may shift dynamically as the price moves; this is normal.
    if bi_dir == -1 and low < bi_candidate.l
        line.set_xy2(current_line, time, low)
    else if bi_dir == 1 and high > bi_candidate.h
        line.set_xy2(current_line, time, high)

[PASTE_YOUR_CODE_HERE_IMMEDIATELY_BEFORE_THE_CLOSING_TAG]