Sumitx369/Paper_Trading_Backtesting
2
1import pytest2 3from app.dsl import DSLError, compile_strategy4from app.dsl.catalog import OP5 6 7def test_code_mode_compiles():8 code = """9def strategy(c):10 buy = c.rsi(14) < 30 and c.close > c.sma(50)11 sell = c.rsi(14) > 7012 return buy, sell13"""14 cs = compile_strategy("code", code=code)15 assert cs.buy_program and cs.sell_program16 # rsi(14) is shared between buy and sell -> deduped to one column17 assert "rsi(14)" in cs.indicators_used18 assert "sma(50)" in cs.indicators_used19 assert sum(1 for s in cs.indicator_specs if s[0] == "rsi") == 120 21 22def test_nocode_crossover():23 spec = {24 "buy": {"op": "crossover", "a": {"ind": "ema", "params": [10]}, "b": {"ind": "ema", "params": [30]}},25 "sell": {"op": "crossunder", "a": {"ind": "ema", "params": [10]}, "b": {"ind": "ema", "params": [30]}},26 }27 cs = compile_strategy("nocode", spec=spec)28 ops = [i[0] for i in cs.buy_program]29 assert OP["CROSSOVER"] in ops30 assert "ema(10)" in cs.indicators_used and "ema(30)" in cs.indicators_used31 32 33def test_prev_and_price_alias():34 code = """35def strategy(c):36 buy = c.price > c.prev(c.close)37 sell = c.close < c.close[-1]38 return buy, sell39"""40 cs = compile_strategy("code", code=code)41 # PUSH_COL with offset 1 should appear (prev / [-1])42 assert any(instr[0] == OP["PUSH_COL"] and instr[3] == 1 for instr in cs.buy_program)43 44 45def test_rejects_arbitrary_code():46 with pytest.raises(DSLError):47 compile_strategy("code", code="def strategy(c):\n buy = __import__('os').system('ls')\n sell = c.close\n")48 49 50def test_requires_buy_and_sell():51 with pytest.raises(DSLError):52 compile_strategy("code", code="def strategy(c):\n buy = c.close > 1\n return buy\n")53 