Implement metaclass for Maximumlikelihood estimator
Instead of constructing the object and then modifying its methods and attributes, you can directly add them in the __new__ method of the metaclass:

class LikelihoodEstimator(type):
    def __new__(cls, name, bases, dct, f):
        def loglike(self, params):
            return f.logpdf(self.endog, *params).sum()

        def fit(self, **kwargs):
            if 'start_params' not in kwargs:
                # This is for performance and! convergence stability.
                # The scipy function provides better starting params.
                kwargs['start_params'] = f.fit(self.endog)
            res = super(cls, self).fit(**kwargs)
            res.df_model = self.nparams
            res.df_resid = len(self.endog) - self.nparams
            return res

        dct.update(loglike=loglike, fit=fit, nparams=len(signature(f.pdf).parameters))
        return super().__new__(cls, name, bases + (GenericLikelihoodModel,), dct)


I also changed the name to more nicely fit within PEP8 guidelines. I also included back bases to avoid undesirable surprises when using this metaclass.



The other option that I think is more easily understandable is to use inheritance instead of metaclasses. There will still be a bit of boilerplate left but the understanding at a glance should overweight:

from scipy.stats import fisk, t
from statsmodels.base.model import GenericLikelihoodModel as _LikelihoodModel
from inspect import signature


class GenericLikelihoodModel(_LikelihoodModel):
    """A maximum likelihood estimator for any distribution"""

    def __init__(self, distribution, endog, exog=None, loglike=None, score=None, hessian=None, missing='none', extra_params_names=None, **kwds)
        self.nparams = len(signature(distribution.pdf).parameters)
        self.distribution = distribution
        super().__init__(endog, exog, loglike, score, hessian, missing, extra_params_names, **kwds)

    def loglike(self, params):
        return self.distribution.logpdf(self.endog, *params).sum()

    def fit(self, **kwargs):
        if 'start_params' not in kwargs:
            # This is for performance and! convergence stability.
            # The scipy function provides better starting params.
            kwargs['start_params'] = self.distribution.fit(self.endog)
        res = super().fit(**kwargs)
        res.df_model = self.nparams
        res.df_resid = len(self.endog) - self.nparams
        return res


class Fisk(GenericLikelihoodModel):
    """A maximum likelihood estimator for the fisk distribution"""
    def __init__(endog, exog=None, loglike=None, score=None, hessian=None, missing='none', extra_params_names=None, **kwds)
        super().__init__(fisk, endog, exog, loglike, score, hessian, missing, extra_params_names, **kwds)


class StudentT(GenericLikelihoodModel):
    """A maximum likelihood estimator for the Student-T distribution"""
    def __init__(endog, exog=None, loglike=None, score=None, hessian=None, missing='none', extra_params_names=None, **kwds)
        super().__init__(t, endog, exog, loglike, score, hessian, missing, extra_params_names, **kwds)