public StudentsTParameters estimateStudentsTParameters() {
		int optDf = 1;
		int optShifting = 0;
		int optXmin = 1;
		double optScaling = 0.0;
		double ksDistance = Double.MAX_VALUE;

		this.x = ArraysExt.filter(this.x,
				FilterFactory.createInstance(FILTER_TYPE.LARGER_THAN, 0));

		if (this.x.length == 0)
			throw new IllegalArgumentException("Empty input");

		int[] dfs = ArraysExt.range(1, 5);
		int[] shiftings = ArraysExt.range(-5, 5);
		int[] xmins = ArraysExt.unique(this.x);
		Arrays.sort(xmins);
		xmins = Arrays.copyOf(xmins, Math.min(xmins.length / 2, 50));

		int maxX = ArraysExt.max(this.x);

		double[] scalings = ArraysExt.range(0.3, 3.0, 0.1);

		double[][][][] cdfsStudents = new double[dfs.length][shiftings.length][scalings.length][];

		for (int xmin : xmins) {
			// System.out.println("###" + xmin);
			int[] z = ArraysExt
					.filter(this.x, FilterFactory.createInstance(
							FILTER_TYPE.LARGER_THAN, xmin));
			double[] zDistr = toDistribution(z);
			double[] empiricalCdf = cdf(zDistr);
			empiricalCdf = ArraysExt.subtract(empiricalCdf[0], empiricalCdf);
			empiricalCdf = ArraysExt.scaleBy(empiricalCdf,
					empiricalCdf[empiricalCdf.length - 1]);

			int posDf = -1;
			for (int df : dfs) {
				posDf++;

				int posShifting = -1;
				for (int shifting : shiftings) {
					posShifting++;

					int posScaling = -1;
					for (double stepsize : scalings) {
						posScaling++;

						double[] studentsTCdf;
						if (cdfsStudents[posDf][posShifting][posScaling] == null)
							cdfsStudents[posDf][posShifting][posScaling] = cdfStudentsT(
									df, maxX, stepsize, shifting);
						studentsTCdf = cdfsStudents[posDf][posShifting][posScaling];

						double diff = studentsTCdf[studentsTCdf.length / 2
								+ xmin - 1];
						studentsTCdf = Arrays.copyOfRange(studentsTCdf,
								studentsTCdf.length / 2 + xmin,
								studentsTCdf.length);
						studentsTCdf = ArraysExt.subtract(studentsTCdf, diff);
						studentsTCdf = ArraysExt.scaleBy(studentsTCdf,
								studentsTCdf[studentsTCdf.length - 1]);

						double dist = cdfDistance(xmin, empiricalCdf,
								studentsTCdf, DISTANCE_TYPE.KS_DISTANCE);
						if (dist < ksDistance) {
							optXmin = xmin;
							optDf = df;
							optShifting = shifting;
							optScaling = stepsize;
							ksDistance = dist;
						}
						// System.out.println(dist);
					}
				}
			}
		}

		return new StudentsTParameters(optDf, optXmin, optShifting, optScaling,
				ksDistance);
	}