Example #1
0
def test_close_sell():
    now = arrow.utcnow()
    epic = Epic()
    tick = Tick(bid=33.3, ask=34.5, datetime=now)
    epic.on_new_tick(tick)

    trade = epic.open_trade(
        direction=TradeDirection.SELL,
        quantity=7,
        ref="MY_TRADE",
        meta={"my_trade_data": "data"},
    )

    # close 3 @ 45.8
    tick = Tick(bid=44.2, ask=45.8, datetime=now)
    epic.on_new_tick(tick)
    epic.close_trade(
        trade=trade,
        quantity=3,
        ref="MY_CLOSE_ID",
        meta={"data": "data"},
    )
    assert trade.closed_quantities == 3
    assert trade.opened_quantities == 4
    assert trade.closed_result_avg == round(33.3 - 45.8, 2)
    assert trade.closed_result == round(33.3 - 45.8, 2) * 3
    assert trade.opened_result_avg == round(33.3 - 45.8, 2)
    assert trade.opened_result == round(33.3 - 45.8, 2) * 4
    assert trade.result_avg == round(33.3 - 45.8, 2)
    assert trade.result == round(33.3 - 45.8, 2) * 7

    assert trade.closed is False

    # close 4 @ 12.4
    tick = Tick(bid=11.1, ask=12.4, datetime=now)
    epic.on_new_tick(tick)
    epic.close_trade(
        trade=trade,
        quantity=4,
    )
    assert trade.closed_quantities == 7
    assert trade.opened_quantities == 0
    assert trade.closed_result_avg == round(
        (round(33.3 - 45.8, 2) * 3 + round(33.3 - 12.4, 2) * 4) / 7, 2
    )
    assert trade.closed_result == round(33.3 - 45.8, 2) * 3 + round(33.3 - 12.4, 2) * 4
    assert trade.opened_result_avg == 0
    assert trade.opened_result == 0
    assert trade.result_avg == round(
        (round(33.3 - 45.8, 2) * 3 + round(33.3 - 12.4, 2) * 4) / 7, 2
    )
    assert trade.result == round(33.3 - 45.8, 2) * 3 + round(33.3 - 12.4, 2) * 4

    assert trade.closed is True
Example #2
0
def test_close_buy():
    now = arrow.utcnow()
    epic = Epic()
    tick = Tick(bid=64.6, ask=68.2, datetime=now)
    epic.on_new_tick(tick)

    trade = epic.open_trade(
        direction=TradeDirection.BUY,
        quantity=6,
        ref="MY_TRADE",
        meta={"my_trade_data": "data"},
    )

    # close 4 @ 54.3
    tick = Tick(bid=54.3, ask=55.6, datetime=now)
    epic.on_new_tick(tick)
    epic.close_trade(
        trade=trade,
        quantity=4,
        ref="MY_CLOSE_ID",
        meta={"data": "data"},
    )
    assert trade.closed_quantities == 4
    assert trade.opened_quantities == 2
    assert trade.closed_result_avg == round(54.3 - 68.2, 2)
    assert trade.closed_result == round(54.3 - 68.2, 2) * 4
    assert trade.opened_result_avg == round(54.3 - 68.2, 2)
    assert trade.opened_result == round(54.3 - 68.2, 2) * 2
    assert trade.result_avg == round(54.3 - 68.2, 2)
    assert trade.result == round(54.3 - 68.2, 2) * 6

    assert trade.closed is False

    # close 2 @ 72.3
    tick = Tick(bid=72.3, ask=73.4, datetime=now)
    epic.on_new_tick(tick)
    epic.close_trade(
        trade=trade,
        quantity=2,
    )
    assert trade.closed_quantities == 6
    assert trade.opened_quantities == 0
    assert trade.closed_result_avg == round(
        (round(54.3 - 68.2, 2) * 4 + round(72.3 - 68.2, 2) * 2) / 6, 2
    )
    assert trade.closed_result == round(54.3 - 68.2, 2) * 4 + round(72.3 - 68.2, 2) * 2
    assert trade.opened_result_avg == 0
    assert trade.opened_result == 0
    assert trade.result_avg == round(
        (round(54.3 - 68.2, 2) * 4 + round(72.3 - 68.2, 2) * 2) / 6, 2
    )
    assert trade.result == round(54.3 - 68.2, 2) * 4 + round(72.3 - 68.2, 2) * 2

    assert trade.closed is True
Example #3
0
def test_init_buy():
    now = arrow.utcnow()
    epic = Epic()
    tick = Tick(bid=54.3, ask=68.9, datetime=now)
    epic.on_new_tick(tick)
    trade = epic.open_trade(
        direction=TradeDirection.BUY,
        quantity=3,
        ref="MY_TRADE",
        meta={"my_trade_data": "data"},
    )

    assert trade.direction == TradeDirection.BUY
    assert trade.open_quantity == 3
    # for a BUY, open value is the input ask
    assert trade.open_value == 68.9
    # current represents the current market value to close this trade
    assert trade.current_close_value == 54.3
    assert trade.datetime == now

    assert trade.closes == []

    # max and min result are the opened result
    assert trade.max_result == round(54.3 - 68.9, 2) * 3
    assert trade.min_result == round(54.3 - 68.9, 2) * 3

    # by default a trade status in confirmed
    assert trade.status == TransactionStatus.CONFIRMED

    assert trade.ref == "MY_TRADE"
    assert trade.meta == {"my_trade_data": "data"}
def test_trade_provider_custom():
    # GIVEN an instance of our custom trade provider attached to an Epic
    trade_provider = MyTradeProvider()
    epic = Epic(ref="MY_EPIC", trade_provider=trade_provider)

    # Add a tick to the epic
    tick = Tick(datetime=arrow.utcnow(), bid=99, ask=101)
    epic.on_new_tick(tick)

    # WHEN I create a new trade add open it with the Trade Provider
    trade = epic.open_trade(direction=TradeDirection.SELL, quantity=2)

    # THEN a new trade is created
    assert len(epic.trade_provider.trades) == 1

    # THEN the trade attribute were updated by the trade provider
    trade_in_provider = epic.trade_provider.trades[0]
    assert trade_in_provider.status == TransactionStatus.PENDING
    assert trade_in_provider.meta["provider_id"] == 123

    # WHEN I close the trade
    epic.close_trade(trade=trade, quantity=1)

    # THEN a close of one quantity was created on the opened trade
    assert len(trade_in_provider.closes) == 1

    # THEN the trade close attributes where set
    trade_close_in_provider = trade_in_provider.closes[0]
    assert trade_close_in_provider.status == TransactionStatus.REQUIRED
    assert trade_close_in_provider.meta["provider_close_id"] == 123
Example #5
0
def test_trade_provider_backtest():
    # GIVEN an instance of our custom trade provider attached to an Epic
    epic = Epic(ref="MY_EPIC")

    # Add a tick to the epic
    tick = Tick(datetime=arrow.utcnow(), bid=99, ask=101)
    epic.on_new_tick(tick)

    # WHEN I create a new trade add open it with the Trade Provider
    trade = epic.open_trade(direction=TradeDirection.SELL, quantity=2)

    # THEN a new trade is created
    assert len(epic.trade_provider.trades) == 1

    # THEN the trade status is automatically set to CONFIRMED
    trade_in_provider = epic.trade_provider.trades[0]
    assert trade_in_provider.status == TransactionStatus.CONFIRMED

    # WHEN I close the trade
    epic.close_trade(trade=trade, quantity=1)

    # THEN a close of one quantity was created on the opened trade
    assert len(trade_in_provider.closes) == 1

    # THEN the trade close attributes where set
    trade_close_in_provider = trade_in_provider.closes[0]
    assert trade_close_in_provider.status == TransactionStatus.CONFIRMED
def test_simple_moving_average():
    # GIVEN A FrameSet in UT1 minutes
    ut1mn = FrameSet(ref="UT1MN", unit=Unit.MINUTE, unit_quantity=1)

    # GIVEN a SMA with a max number of periods of 10
    sma = SimpleMovingAverage(ref="SMA", max_periods=10)
    ut1mn.add_indicator(sma)

    # GIVEN an Epic holding the UT4MN FrameSet
    epic = Epic(ref="MY_EPIC_CODE")
    epic.add_frame_set(ut1mn)

    # GIVEN an instance of my provider
    provider = MyTickProvider(epics=[epic])

    # WHEN I run the tick provider
    provider.run()

    # THEN the SMA on the last 3 periods is properly calculated
    sma3 = epic.get_indicator_value(
        frame_set_ref="UT1MN",
        indicator_ref="SMA",
    ).get_value(periods=3)
    assert sma3 == round((9.4 + 14.7 + 11.8) / 3, 2)

    # WHEN I update the epic with a new tick, the SMA is updated
    new_tick = Tick(datetime=epic.last_tick.datetime, bid=15.6, ask=17.6)
    epic.on_new_tick(new_tick)

    # THEN the SMA on the last 3 periods is properly updated
    sma3 = epic.get_indicator_value(
        frame_set_ref="UT1MN",
        indicator_ref="SMA",
    ).get_value(periods=3)
    assert sma3 == round((9.4 + 14.7 + 16.6) / 3, 2)
Example #7
0
def test_trade():
    # GIVEN an Epic
    epic = Epic(ref="MY_EPIC_CODE")

    # GIVEN a tick added to this epic (to set the epic last value to 100)
    tick1 = Tick(
        datetime=arrow.get("2020-01-01 12:34:56"),
        bid=99,
        ask=101,
    )
    epic.on_new_tick(tick1)

    # WHEN I open a BUY Trade with a quantity of 3 from the current epic value.
    trade = epic.open_trade(
        direction=TradeDirection.BUY,
        quantity=3,
    )

    # THEN the trade result is the current spread
    assert trade.result == -6

    # WHEN a new tick is received by the epic
    tick2 = Tick(
        datetime=arrow.get("2020-01-01 12:34:57"),
        bid=109,
        ask=111,
    )
    epic.on_new_tick(tick2)

    # THEN the trade result is updated
    assert trade.result == 24

    # WHEN I close 2 quantities on this trade
    epic.close_trade(trade=trade, quantity=2)

    assert trade.closed_quantities == 2

    # WHEN a new tick is received by the epic
    tick3 = Tick(
        datetime=arrow.get("2020-01-01 12:34:57"),
        bid=89,
        ask=91,
    )
    epic.on_new_tick(tick3)

    # THEN the trade result is updated and take account that one quantity is closed.
    assert trade.result == 4
Example #8
0
def test_value():
    tick = Tick(
        datetime.utcnow().replace(tzinfo=timezone.utc),
        bid=49,
        ask=50,
    )

    assert tick.value == 49.5
Example #9
0
def test_value():
    tick = Tick(
        datetime.utcnow().replace(tzinfo=timezone.utc),
        bid=99,
        ask=101,
    )

    assert tick.spread == 2
Example #10
0
def test_arrow_datetime():
    now = arrow.utcnow()
    tick = Tick(
        datetime=now,
        bid=49,
        ask=50,
    )

    assert tick.datetime == now
Example #11
0
def test_python_datetime():
    now = datetime.utcnow().replace(tzinfo=timezone.utc)
    tick = Tick(
        datetime=now,
        bid=49,
        ask=50,
    )

    assert tick.datetime == arrow.get(now)
Example #12
0
def test_basic_strategy():
    epic = Epic(ref="MY_EPIC_CODE")

    # GIVEN a instance of MyStrategy on an Epic
    strategy = MyStrategy()
    epic.add_strategy(strategy)

    # WHEN a tick of value 100 is received
    tick = Tick(arrow.utcnow(), 99, 101)
    epic.on_new_tick(tick)
    # THEN a trade is created
    assert len(epic.trade_provider.opened_trades) == 1

    # WHEN a tick of value != 100 is received
    tick = Tick(arrow.utcnow(), 101, 103)
    epic.on_new_tick(tick)
    # THEN the previously opened trade is closed
    assert len(epic.trade_provider.opened_trades) == 0
Example #13
0
 def run(self):
     for i in range(10):
         # create a new tick
         new_tick = Tick(
             datetime=datetime.utcnow().replace(tzinfo=timezone.utc),
             bid=(i - 0.5),
             ask=(i + 0.5),
         )
         # find epic to attach the tick to
         tick_epic = self.get_epic_by_ref("MY_EPIC_CODE")
         # attach tick to epic
         tick_epic.on_new_tick(new_tick)
Example #14
0
def test_tick():
    now_tokyo = arrow.now("Asia/Tokyo")
    tick = Tick(datetime=now_tokyo, bid=99, ask=101, meta={"my_data": "data"})

    assert tick.bid == 99
    assert tick.ask == 101
    assert tick.datetime == now_tokyo
    assert tick.meta == {"my_data": "data"}

    assert tick.value == 100.0  # value represents the mean between bid and ask
    assert tick.spread == 2.0  # spread is the difference between bid and ask
    assert tick.datetime_utc == now_tokyo.to("UTC")
Example #15
0
 def run(self):
     # Generates 9 ticks
     for i in range(10):
         # create a new tick
         new_tick = Tick(
             datetime=arrow.utcnow(),
             bid=(i - 0.5),
             ask=(i + 0.5),
         )
         # find epic to attach the tick to
         tick_epic = self.get_epic_by_ref("MY_EPIC_CODE")
         # dispatch tick to epic
         tick_epic.on_new_tick(new_tick)
Example #16
0
    def run(self):
        current_datetime = arrow.utcnow()

        i = 0
        while i < 10:
            tick = Tick(
                bid=i - 0.2,
                ask=i + 0.2,
                datetime=current_datetime,
            )
            self.get_epic_by_ref("MY_EPIC").on_new_tick(tick)

            current_datetime = current_datetime + timedelta(minutes=1)
            i += 0.01
Example #17
0
def test_asdict():
    now = arrow.utcnow()
    tick = Tick(
        now,
        bid=49,
        ask=50,
    )

    assert tick.asdict() == {
        "ask": 50.0,
        "bid": 49.0,
        "datetime": now,
        "spread": 1.0,
        "value": 49.5,
    }

    assert tick.asdict(datetime_to_str=True) == {
        "ask": 50.0,
        "bid": 49.0,
        "datetime": now.strftime("%Y-%m-%d %H:%M:%S"),
        "spread": 1.0,
        "value": 49.5,
    }
 def run(self):
     # Generate 8 ticks (1 tick every minute from 2020-01-01 00:00:12)
     dt = arrow.get("2020-01-01 00:00:00")
     for i in [12, 13.4, 8.2, 10, 12.6, 9.4, 14.7, 11.8]:
         # create a new tick
         new_tick = Tick(
             datetime=dt,
             bid=(i - 0.5),
             ask=(i + 0.5),
         )
         # find epic to attach the tick to
         tick_epic = self.get_epic_by_ref("MY_EPIC_CODE")
         # dispatch tick to epic
         tick_epic.on_new_tick(new_tick)
         dt = dt.shift(minutes=1)
Example #19
0
 def run(self):
     # Generate 10 ticks (1 tick every minute from 2020-01-01 00:00:12)
     dt = arrow.get("2020-01-01 00:00:12")
     for i in range(10):
         dt = dt.shift(minutes=1)
         # create a new tick
         new_tick = Tick(
             datetime=dt,
             bid=(i - 0.5),
             ask=(i + 0.5),
         )
         # find epic to attach the tick to
         tick_epic = self.get_epic_by_ref("MY_EPIC_CODE")
         # dispatch tick to epic
         tick_epic.on_new_tick(new_tick)
Example #20
0
def test_create_epic():
    # GIVEN an epic timezoned on Paris(France) holding a max of 3 ticks in memory
    epic = Epic(timezone="Europe/Paris")

    # WHEN I add a tick to this epic in UTC
    tick = Tick(
        datetime=arrow.utcnow(),
        bid=100,
        ask=101,
    )
    epic.on_new_tick(tick)

    # THEN the tick is set as the Epic last tick
    assert epic.last_tick == tick

    # THEN the tick date was converted from UTC to the Epic timezone (Europe/Paris)
    assert tick.datetime.tzinfo == tz.gettz(epic.timezone)
Example #21
0
def test_init_sell():
    now = arrow.utcnow()
    epic = Epic()
    tick = Tick(bid=34, ask=36, datetime=now)
    epic.on_new_tick(tick)
    trade = epic.open_trade(
        direction=TradeDirection.SELL,
        quantity=7,
    )

    assert trade.direction == TradeDirection.SELL
    assert trade.open_quantity == 7
    # for a SELL, open value is the input bid
    assert trade.open_value == 34
    # current represents the current market value to close this trade
    assert trade.current_close_value == 36
    assert trade.datetime == now

    assert trade.closes == []

    # max and min result are the opened result
    assert trade.max_result == (34 - 36) * 7
    assert trade.min_result == (34 - 36) * 7
Example #22
0
def test_convert_to_string():
    now = arrow.utcnow()
    tick = Tick(datetime=now, bid=999, ask=1001)

    assert (str(tick) == f"{now.strftime('%Y-%m-%d %H:%M:%S')} : 1000.0 "
            f"(bid: 999.0, ask: 1001.0, spread: 2.0)")
Example #23
0
def test_indicator_market_open_gaps():
    my_indicator = BaseIndicator(ref="MY_IND",
                                 value_class=BaseIndicatorValue,
                                 market_open_only=True)
    daily_frameset = FrameSet(ref="UT1D", unit=Unit.DAY, unit_quantity=1)
    daily_frameset.add_indicator(my_indicator)

    # GIVEN an epic open between 9 and 18 on Tuesday and Thursday
    epic = Epic(open_time=time(9, 0),
                close_time=time(18, 0),
                trade_days=[1, 3])
    epic.add_frame_set(daily_frameset)

    # Add ticks on Monday: Market is closed, the indicator value stays to None
    tick1 = Tick(datetime=arrow.get("2020-01-06 08:00:00"), bid=999, ask=1001)
    epic.on_new_tick(tick1)

    last_frame = epic.frame_sets["UT1D"].current
    assert last_frame.period_start == arrow.get("2020-01-06 00:00:00")
    assert last_frame.indicators["MY_IND"] is None

    tick2 = Tick(datetime=arrow.get("2020-01-06 10:00:00"), bid=999, ask=1001)
    epic.on_new_tick(tick2)
    assert last_frame.indicators["MY_IND"] is None

    tick3 = Tick(datetime=arrow.get("2020-01-06 19:00:00"), bid=999, ask=1001)
    epic.on_new_tick(tick3)
    assert last_frame.indicators["MY_IND"] is None

    # Add ticks on Tuesday: Market is opened, the indicator value is updated
    tick4 = Tick(datetime=arrow.get("2020-01-07 08:00:00"), bid=999, ask=1001)
    epic.on_new_tick(tick4)

    last_frame = epic.frame_sets["UT1D"].current
    assert last_frame.period_start == arrow.get("2020-01-07 00:00:00")
    assert last_frame.indicators["MY_IND"] is None

    tick5 = Tick(datetime=arrow.get("2020-01-07 10:00:00"), bid=999, ask=1001)
    epic.on_new_tick(tick5)
    assert last_frame.indicators["MY_IND"].first_tick == tick5

    tick6 = Tick(datetime=arrow.get("2020-01-07 11:00:00"), bid=1005, ask=1007)
    epic.on_new_tick(tick6)
    assert last_frame.indicators["MY_IND"].high_tick == tick6

    tick7 = Tick(datetime=arrow.get("2020-01-07 12:00:00"), bid=997, ask=999)
    epic.on_new_tick(tick7)
    assert last_frame.indicators["MY_IND"].low_tick == tick7

    tick8 = Tick(datetime=arrow.get("2020-01-07 17:00:00"), bid=999, ask=1001)
    epic.on_new_tick(tick8)
    assert last_frame.indicators["MY_IND"].last_tick == tick8

    tick9 = Tick(datetime=arrow.get("2020-01-07 19:00:00"), bid=999, ask=1001)
    epic.on_new_tick(tick9)
    assert last_frame.indicators["MY_IND"].first_tick == tick5
    assert last_frame.indicators["MY_IND"].high_tick == tick6
    assert last_frame.indicators["MY_IND"].low_tick == tick7
    assert last_frame.indicators["MY_IND"].last_tick == tick8

    # Add ticks on Wednesday: Market is closed, the indicator value stays to None
    tick10 = Tick(datetime=arrow.get("2020-01-08 08:00:00"), bid=999, ask=1001)
    epic.on_new_tick(tick10)

    last_frame = epic.frame_sets["UT1D"].current
    assert last_frame.period_start == arrow.get("2020-01-08 00:00:00")
    assert last_frame.indicators["MY_IND"] is None
    assert last_frame.previous_frame.indicators["MY_IND"].last_tick == tick8

    tick11 = Tick(datetime=arrow.get("2020-01-08 12:00:00"), bid=999, ask=1001)
    epic.on_new_tick(tick11)
    assert last_frame.indicators["MY_IND"] is None

    tick12 = Tick(datetime=arrow.get("2020-01-08 19:00:00"), bid=999, ask=1001)
    epic.on_new_tick(tick12)
    assert last_frame.indicators["MY_IND"] is None

    # Add ticks on Thursday: Market is opened, the indicator value is updated
    tick13 = Tick(datetime=arrow.get("2020-01-09 08:00:00"), bid=999, ask=1001)
    epic.on_new_tick(tick13)

    last_frame = epic.frame_sets["UT1D"].current
    assert last_frame.period_start == arrow.get("2020-01-09 00:00:00")
    assert last_frame.indicators["MY_IND"] is None

    tick14 = Tick(datetime=arrow.get("2020-01-09 10:00:00"), bid=999, ask=1001)
    epic.on_new_tick(tick14)
    assert last_frame.indicators["MY_IND"].first_tick == tick14
    assert last_frame.indicators["MY_IND"].previous.last_tick == tick8