How would you code this system? Let's compare platforms.

Discussion in 'Strategy Building' started by lindq, Aug 2, 2021.

  1. kmiklas

    kmiklas

    Yeah so a best-practice for stuff like is to center the system on rule sets. They can be maintained in excel, and saved as a .csv. All these ANDs and ORs are clumsy, difficult to debug/maintain, and to be avoided.

    Create n rule sets and apply the ones you want; E.g.:

    Set 1: Action: BUY 100
    Code:
    OP, lt, CL.1*.98
    CL.1,lt,MA.1
    MPD#SPYOP.1,lt,MPD#SPYCL.1
    DAY,ne,5
    

    or as JSON:
    Code:
    [
        "TSLA": {
            "action": {
                 "side": "buy",
                 "qty": 100,
                 // etc
            },
            "rule": [ // array
                {
                    "lhs": "OP",
                    "oper": "lt",
                    "rhs": "MA.1"
                 },
                 {
                 "lhs": "CL.1"
                 // etc
        }
    
    A rule engine parses market data. When the stars align and all rules within a set evaluate to true, take specified action. Written in a functional style/language like Haskell or even modern C++!

    Market data are stored as rows in a database. Advance a pointer through the datasets, test rules at every iteration. Probably MariaDB or Postgres. Personally I like to store times for a day as units from market open (so for US equities 9:30:00.000000ET is time 0). This is debatable but I like it for different reasons. Regardless, times must be properly synched for accurate results.

    As for language for the framework, I'd use Python or Kotlin, unless things get too slow, then C++, Go, or even just C.

    This architecture permits quick and easy testing of a variety of rule sets: just add them into excel and dump it as a .csv or JSON structure. Rule sets can even be generated; e.g. write a little script to generate rules ranging +/-5% stepping by 1%. Write the csv, feed it into the rule engine, and see what it spits out. Rules can even be dynamically added/modified as market conditions change.

    Rule sets can also be created for results; set rules to detect anomalies in the data and write out a report for idea generation.

    If you have a Mac, look at their "Advanced Search" in Finder for a simple example of a rule set and engine. It finds files based on a set of rules and conditions you provide.
     
    Last edited: Aug 2, 2021
    #11     Aug 2, 2021
    yc47ib, fan27 and lindq like this.
  2. Metamega

    Metamega

    Amibroker look a little like that.

    Code:
    SetOption("ActivateStopsImmediately",True);
    SetTradeDelays(0,0,0,0);
    
    condition1 = 1;// Name() == "TQQQ";
    condition2 = Open < Ref(Close,-2) * 1.98;
    condition3 = Ref(Close,-1) < Ref(MA(Close,5),-1);
    snp500 = Foreign("SPY","Close");
    condition4 = Ref(snp500,-1) < Ref(snp500,-2) AND DayOfWeek() != 1; // 1 = monday
    
    Buy = condition1 AND condition2 AND condition3 AND condition4;
    Sell = 0;
    
    BuyPrice = Open;
    
    ApplyStop(stopTypeLoss,stopModePercent, 4);
    ApplyStop(stopTypeNBar,stopModeBars,0,0);
     
    #12     Aug 2, 2021
    shuraver, yc47ib and lindq like this.
  3. I don't care about the number of lines the code takes. For me is the readability by far the most important aspect. It is easy to make mistakes if you can't read it properly. My preferred software language is Java. If I have a combination of multiple entry (or exit) conditions I would code it something like this:
    Code:
    boolean isEntry() {
        ArrayList<boolean> Conditions = new ArrayList<>();
        Conditions.add(Open < 0.98*Close[-2]);
        Conditions.add(Close[-1] < SMA(5));
        Conditions.add(SPYClose[-1] < SPYOpen[-1]);
        Conditions.add(Day != 5);
        boolean Result;
        if(Conditions.contains(false)) Result = false;
        else Result = true;
        return Result;
    }
    
    P.S. I use IB's TWS API for my automated trading.
     
    Last edited: Aug 2, 2021
    #13     Aug 2, 2021
    yc47ib, Option_Attack and lindq like this.
  4. kmschu026

    kmschu026

    Tradestation Code:

    //Data 1: TQQQ 1-Minute Bars (For Trading)
    //Data 2: TQQQ Daily Bars (For Signal)
    //Data 3: SPY Daily Bars (For Signal)

    If Date<>Date[1]
    And MarketPosition = 0
    And OpenD(0)/CloseD(2) < 0.98
    And CloseD(1) < Average(C of Data2, 5)[1]
    And CloseD(1) of Data3 < OpenD(1) of Data3
    And DayOfWk <5
    Then Buy next bar at market;

    If MarketPosition > 0
    And Close > OpenD(0)*1.04
    Then Sell next bar at market;

    Setexitonclose;
     
    #14     Aug 2, 2021
    shuraver, yc47ib and lindq like this.
  5. lindq

    lindq

    Thank you all for posting. Anyone working with Ninja, or other languages, who cares to share how they'd approach this?

    FYI: When outlining the conditions of the test in my original post, I just jotted down some random thoughts for the exercise. But when actually running it this morning, I found, surprise, it produced over 100% gain over 3 years. Which is not too shabby considering the variation in vol over that time. And it will do better with a few tweaks. Here are my results, as per my original post. See what you can come up with. (No commissions or costs included. 30K per trade)


    Backtest [2018-08-04 - 2021-08-03] Symbol TQQQ Periodicity: Daily

    Avg Profit/Trade $339.16 Avg Position Size $29,757.46
    Avg % Gain/Trade 1.140% Avg % Gain/Bar ???
    Gross profit $34,255.39 Maximum Drawdown $3,046.95
    Commissions $0.00 Average Drawdown $288.16
    Net Profit $34,255.39 Ratio Avg Win/Avg Loss 0.92
    Total # Of Trades 101 Percent Profitable 70%
    Winning Trades 71 Losing Trades 30
    Largest Winning Trade $1,199.98 Largest Losing Trade $3,046.95
    Average Winning Trade $892.39 Average Losing Trade $970.15
    Max Consec. Winners 13 Max Consec. Losers 3
    Avg # Bars In Winners 0 Avg # Bars In Losers 0
     
    Last edited: Aug 3, 2021
    #15     Aug 3, 2021
    yc47ib likes this.
  6. fan27

    fan27

    I have something similar. One thing I had to do was add the ability to inject values into the JSON from the strategy parameter list, thus being able to hook up my framework to the built in optimizer in Tickblaze.
     
    #16     Aug 3, 2021
    kmiklas likes this.
  7. MarkBrown

    MarkBrown

    i am a visual guy, i want to see the system i am building. i dont have the data specified so i used what i have which is SPX.X0 {sp cash} and M2K# {russell 2000} as proxy. using 4% pft looks to be quite a lot as signified by the red dots for exits. on the other hand i marked the high of the session with a yellow dot and in most cases it makes a good profit compared to the entry criteria. so green is buy and yellow is the session high and red is the 4% target. ~m

    // multicharts code {easy language}

    var:nogo(0);
    if c data2<c data2[1]and dayofweek(date)<>5 then begin nogo=1;end;
    if (o*.98)<c[2]and c[1]<average(c,5)and nogo2=0 then begin plot1(c,"buy");
    plot2(o*1.04,"pft");
    plot79(h,"high");end;

    nogo=0;



    [​IMG]
     
    #17     Aug 3, 2021
    shuraver, yc47ib and lindq like this.
  8. If merely doing a trade:
    In TOS, one could do something like this entered as a 1st triggers OCO (Just copy&past the three lines below into the TOS order entry after configuring for 1st trgs OCO)
    BUY +100 TQQQ MKT GTC WHEN TQQQ STUDY '(open<=(close[2])*.98) and close[1]<movingaverage(averagetype.simple,close[1],5) and close(symbol="SPY")[1]<close(symbol="SPY") and getdayofweek(getyyyymmdd())!=5 ;D' IS TRUE
    SELL -100 TQQQ MKT GTC TRG BY OCO WHEN TQQQ STUDY 'close>open*1.04 ;D' IS TRUE
    SELL -100 TQQQ MOC GTC TRG BY OCO


    ----------------
    Errata: That MOC order may not work as part of an OCO group, so some more work may be required to have the trade automated to close at market close.
     
    Last edited: Aug 3, 2021
    #18     Aug 3, 2021
    yc47ib likes this.
  9. Mine is very close to yours. Formatting is boogered, but the data is there:

    Net Profit % 108.79% 108.79% 0.00% 298.13%
    Annualized Gain % 27.90% 27.90% 0.00% 58.69%
    Exposure 0.00% 0.00% 0.00% 100.00%

    Number of Trades 106 106 0 1
    Avg Profit/Loss $328.42 $328.42 $0.00 $95,401.54
    Avg Profit/Loss % 1.11% 1.11% 0.00% 295.76%
    Avg Bars Held 1.00 1.00 0.00 752.00

    Winning Trades 74 74 0 1
    Winning % 69.81% 69.81% N/A 100.00%
    Gross Profit $66,661.09 $66,661.09 $0.00 $95,401.54
    Avg Profit $900.83 $900.83 $0.00 $95,401.54
    Avg Profit % 3.03% 3.03% 0.00% 295.76%
    Avg Bars Held 1.00 1.00 0.00 752.00
    Max Consecutive 12 12 0 N/A

    Losing Trades 32 32 0 0
    Losing % 30.19% 30.19% N/A 0.00%
    Gross Loss $-31,848.33 $-31,848.33 $0.00 $0.00
    Avg Loss $-995.26 $-995.26 $0.00 $0.00
    Avg Loss % -3.34% -3.34% 0.00% 0.00%
    Avg Bars Held 1.00 1.00 0.00 0.00
    Max Consecutive 4 4 0 N/A

    Max Drawdown $-6,038.98 $-6,038.98 $0.00 $-39,711.36
    Max Drawdown % -16.19% -16.19% 0.00% -70.25%
    Max Drawdown Date 6/3/2019 6/3/2019 N/A 3/20/2020

    Wealth-Lab Score 0.00 0.00 0.00 17.46
    Profit Factor 2.09 2.09 0.00 INF
    Recovery Factor 5.76 5.76 N/A 2.40
    Payoff Ratio 0.91 0.91 0.00 INF
    Sharpe Ratio 1.68 1.68 0.00 1.01
    Ulcer Index 5.81 5.81 0.00 22.98
    Wealth-Lab Error Term 7.14 7.14 0.00 16.56
    Wealth-Lab Reward Ratio 3.90 3.90 N/A 3.54
    Luck Coefficient 1.32 1.32 0.00 1.00
    Pessimistic Rate of Return 1.58 1.58 0.00 0.00
    Equity Drop Ratio 0.15 0.15 0.00 0.15



     
    #19     Aug 3, 2021
  10. lindq

    lindq

    That's an interesting way to visualize the data. Thanks for sharing. If the red dots do represent the daily high reaching the profit target, that does happen quite often with TQQQ. It's not an instrument I actually trade, but the random signals I posted just happened to catch the moves.
     
    Last edited: Aug 3, 2021
    #20     Aug 3, 2021
    MarkBrown likes this.