Fala ai Lucas, tudo bem? Fiz umas alterações aqui, primeiro na NegociacoesView na função template:
<tbody class="table-body">
                ${model.negociacoes
                  .map(
                      (n, i) => `
                    <tr>
                        <td>${DateHelper.dateToText(n.data)}</td>
                        <td>${n.quantidade}</td>
                        <td>${n.valor}</td>
                        <td>${n.volume}</td>
                        <td data-index="${i}" onclick="negociacaoController.remover(this)">X</td>
                    </tr>
                `
                  )
                  .join('')}
</tbody>
Modifiquei o tbody, basicamente adicione o index do array como segundo parâmetro do map e passei ele para um data attribute no td.
Também chamei a função remover do negociacaoController que recebe o próprio td.
Agora na classe NegociacaoController criei a função para remover:
remover(td) {
    const index = td.dataset.index;
    if (index >= 0) {
      this._listaNegociacoes.remove(index);
    }
  }
Ela pega o data attribute e verifique se o mesmo existe, se sim ela chama a função remove da ListaNegociacoes.
Na classe ListaNegociacoes adicionei uma função remove:
remove(index) {
    const novaLista = [...this._negociacoes];
    novaLista.splice(index, 1);
    this._negociacoes = novaLista
  }
Ela cria uma nova lista e remove um item dado uma posição específica do array.
E por último na NegociacaoController precisa fazer o bind dessa nova função remove:
this._listaNegociacoes = new Bind(
      new ListaNegociacoes(),
      new NegociacoesView(this._$('#negociacoesView')),
      'adicionaNegociacoes',
      'esvaziaNegociacoes',
      'ordenarLista',
      'inverterLista',
      'remove',
    );
Acho que foi isso, a ideia seria mais ou menos essa.
Claro que tem N jeitos de se implementar essa remoção, a que eu pensei aqui foi essa.
Espero ter ajudado.