nodes: 0, module; 1, function_definition; 2, function_name:sortino_ratio; 3, parameters; 4, block; 5, identifier:self; 6, default_parameter; 7, default_parameter; 8, default_parameter; 9, expression_statement; 10, expression_statement; 11, return_statement; 12, identifier:threshold; 13, float:0.0; 14, identifier:ddof; 15, integer:0; 16, identifier:freq; 17, None; 18, comment:"""Return over a threshold per unit of downside deviation.
  
          A performance appraisal ratio that replaces standard deviation
          in the Sharpe ratio with downside deviation.
          [Source: CFA Institute]
  
          Parameters
          ----------
          threshold : {float, TSeries, pd.Series}, default 0.
              While zero is the default, it is also customary to use
              a "minimum acceptable return" (MAR) or a risk-free rate.
              Note: this is assumed to be a *periodic*, not necessarily
              annualized, return.
          ddof : int, default 0
              Degrees of freedom, passed to pd.Series.std().
          freq : str or None, default None
              A frequency string used to create an annualization factor.
              If None, `self.freq` will be used.  If that is also None,
              a frequency will be inferred.  If none can be inferred,
              an exception is raised.
  
              It may be any frequency string or anchored offset string
              recognized by Pandas, such as 'D', '5D', 'Q', 'Q-DEC', or
              'BQS-APR'.
  
          Returns
          -------
          float
          """; 19, assignment; 20, binary_operator:(self.anlzd_ret() - threshold) / stdev; 21, identifier:stdev; 22, call; 23, parenthesized_expression; 24, identifier:stdev; 25, attribute; 26, argument_list; 27, binary_operator:self.anlzd_ret() - threshold; 28, identifier:self; 29, identifier:semi_stdev; 30, keyword_argument; 31, keyword_argument; 32, keyword_argument; 33, call; 34, identifier:threshold; 35, identifier:threshold; 36, identifier:threshold; 37, identifier:ddof; 38, identifier:ddof; 39, identifier:freq; 40, identifier:freq; 41, attribute; 42, argument_list; 43, identifier:self; 44, identifier:anlzd_ret
code: def sortino_ratio(self, threshold=0.0, ddof=0, freq=None):
          """Return over a threshold per unit of downside deviation.
  
          A performance appraisal ratio that replaces standard deviation
          in the Sharpe ratio with downside deviation.
          [Source: CFA Institute]
  
          Parameters
          ----------
          threshold : {float, TSeries, pd.Series}, default 0.
              While zero is the default, it is also customary to use
              a "minimum acceptable return" (MAR) or a risk-free rate.
              Note: this is assumed to be a *periodic*, not necessarily
              annualized, return.
          ddof : int, default 0
              Degrees of freedom, passed to pd.Series.std().
          freq : str or None, default None
              A frequency string used to create an annualization factor.
              If None, `self.freq` will be used.  If that is also None,
              a frequency will be inferred.  If none can be inferred,
              an exception is raised.
  
              It may be any frequency string or anchored offset string
              recognized by Pandas, such as 'D', '5D', 'Q', 'Q-DEC', or
              'BQS-APR'.
  
          Returns
          -------
          float
          """
  
          stdev = self.semi_stdev(threshold=threshold, ddof=ddof, freq=freq)
          return (self.anlzd_ret() - threshold) / stdev