Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    1. Home
    2. jaezilla
    3. Posts
    For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/
    J
    • Profile
    • Following 0
    • Followers 0
    • Topics 0
    • Posts 2
    • Best 1
    • Groups 0

    Posts made by jaezilla

    • RE: Need help/advice for dynamically implementing commissions

      Definitely not efficient, but I manually do it by saving all the trades and then iterating through them in post processing:

       def notify_trade(self,trade):
              self.trades.setdefault(self.data._name, [] ).append(trade)
      
      trades_dict:dict = {}
      for trade in result.trades.get(symbol, []):
      
          if trade.status == 1:
      
              trades_dict[trade.baropen] = {'open': {'size': trade.size, 'price': trade.price, 'value': trade.value } }
      
          elif trade.status == 2:
              size = trades_dict.get(trade.baropen).get('open').get('size')
              open_price = trades_dict.get(trade.baropen).get('open').get('price')
              open_value = trades_dict.get(trade.baropen).get('open').get('value')
              close_value = open_value + trade.pnl
              close_price = close_value / size
      
              open_commission =  min ( max (min_commision, (size * commission_rate_per_share) ), ( max_commision_pct *  size * open_price  ) ) 
              close_commission = min ( max (min_commision, (size * commission_rate_per_share) ), ( max_commision_pct *  close_value  ) ) 
              close_fee = close_value * trns_fee_pct
              close_fee += min ( (size * finra_sell_fee_per_share) , finra_max_fee_amount)
      

      Interactive Brokers has a size based commission with a min and max limit. There is also a value based fee assessed on closing a position. This only works with opening and closing a position in its entirety.

      posted in General Code/Help
      J
      jaezilla
    • RE: Dynamically set params and lines attribute of class PandasData

      Here is an example of what I did:

      Generating the lines and params tuples by passing in list(df.columns)

      def get_extra_df_columns(self, df_columns: list[str] = []) -> list[tuple]:
          lines: tuple = ()
          params: tuple(tuple) = ()
          for column in df_columns:
              if column not in ['symbol', 'open', 'high', 'low', 'close', 'volume']:
                  lines = lines + (column,)
                  params = params + ( (column, -1), )
      
          return [lines, params]
      

      Creating the subclass by parsing the df to be parsed then returning it with the subclass attributes set dynamically:

      def _create_data_feeder(self, database: Database, df: pd.DataFrame ):
      
              lines, params = database.get_extra_df_columns(df_columns=list(df.columns) )
              return type('PandasDataFeed', (bt.feeds.PandasData, ), {'lines':lines, 'params':params} )
      
      

      Adding the dataframe to cerebro via the created data_feeder subclass

      self.data_feeder = self._create_data_feeder(database=database, df=df)
      self.cerebro.adddata(self.data_feeder(dataname=df, name=symbol ))
      

      The extra columns in the df are vwap and supertrend and are accessible without hardcoding the lines and params

      class TestStrategy(bt.Strategy):
      
          def __init__(self):
      
              for i, d in enumerate(self.datas):
       
                  bt.ind.SMA(d.supertrend, period=1, subplot=False, plotname='supertrend')
                  bt.ind.SMA(d.vwap, period=1, subplot=False, plotname='vwap')
      
      posted in General Code/Help
      J
      jaezilla
    • 1 / 1