def optimize_fit(self,obj_type,printer=True):

		# Starting parameters
		phi = np.zeros(self.param_no)
		rounding_points = 4

		# Starting values
		if self.model_type == 'GAS':
			if self.dist in ['Laplace','Normal']:
				phi[0] = np.mean(self.data)
			elif self.dist == 'Poisson':
				phi[0] = np.log(np.mean(self.data))
		elif self.model_type == 'VAR':
			phi = self.create_B_direct().flatten()
			cov = self.estimate_cov()

			# Inelegant - needs refactoring
			for i in range(self.ylen):
				for k in range(self.ylen):
					if i == k:
						phi = np.append(phi,self.param_desc[len(phi)]['prior'].itransform(cov[i,k]))
					elif i > k:
						phi = np.append(phi,self.param_desc[len(phi)]['prior'].itransform(cov[i,k]))			
		elif self.model_type == 'GARCH':
			phi = np.ones(self.param_no)*0.00001
			phi[0] = self.param_desc[0]['prior'].itransform(np.mean(np.power(self.data,2)))
		elif self.model_type == 'EGARCH':
			phi[0] = self.param_desc[0]['prior'].itransform(np.log(np.mean(np.power(self.data,2))))
		elif self.model_type == 'GPNARX':
			phi = np.ones(self.param_no)*-1.0
			arma_start = arma.ARIMA(self.data,ar=self.ar,ma=0,integ=self.integ)
			arma_start.fit(printer=False)
			phi[0] = log(exp(arma_start.params[len(arma_start.params)-1])**2)			
		elif self.model_type in ['LLT','LLEV']:
			phi = np.ones(self.param_no)*-0.0
			rounding_points=10

		# Optimize using L-BFGS-B
		p = optimize.minimize(obj_type,phi,method='L-BFGS-B')
		self.params = copy.deepcopy(p.x)

		# Vector for transformed parameters
		t_params = copy.deepcopy(p.x)			

		# Check that matrix is non-singular; act accordingly
		try:
			self.ihessian = np.linalg.inv(nd.Hessian(obj_type)(self.params))
			self.ses = np.abs(np.diag(self.ihessian))**0.5

			t_p_std = copy.deepcopy(self.ses) # vector for transformed standard errors
			
			# Create transformed variables
			for k in range(len(t_params)-self.param_hide):
				z_temp = (p.x[k]/float(self.ses[k]))
				t_params[k] = self.param_desc[k]['prior'].transform(t_params[k])
				t_p_std[k] = t_params[k] / z_temp

			# Replace with something more elegant in future versions
			if printer is True:

				data = []

				for i in range(len(self.param_desc)-self.param_hide):
					if self.param_desc[i]['prior'].transform == np.array:
						data.append({
							'param_name': self.param_desc[i]['name'], 
							'param_value':round(self.param_desc[i]['prior'].transform(p.x[i]),rounding_points), 
							'param_std': round(t_p_std[i],rounding_points),
							'param_z': round(t_params[i]/float(t_p_std[i]),rounding_points),
							'param_p': round(tst.find_p_value(t_params[i]/float(t_p_std[i])),rounding_points),
							'ci': "(" + str(round(t_params[i] - t_p_std[i]*1.96,rounding_points)) + " | " + str(round(t_params[i] + t_p_std[i]*1.96,rounding_points)) + ")"})
					else:
						data.append({
							'param_name': self.param_desc[i]['name'], 
							'param_value':round(self.param_desc[i]['prior'].transform(p.x[i]),rounding_points)})						
				fmt = [
				    ('Parameter',       'param_name',   40),
				    ('Estimate',          'param_value',       10),
				    ('Standard Error', 'param_std', 15),
				    ('z',          'param_z',       10),
				    ('P>|z|',          'param_p',       10),
				    ('95% Confidence Interval',          'ci',       25)
				]

		except: # If Hessian is not invertible...
			print "Hessian not invertible! Consider a different model specification."
			print ""

			# Reset iHessian and standard errors, reflecting non-invertibility
			self.ihessian = []
			self.ses = []

			# Transform parameters
			for k in range(len(t_params)):
				t_params[k] = self.param_desc[k]['prior'].transform(t_params[k])

			if printer is True:

				data = []

				for i in range(len(self.param_desc)):
					data.append({'param_name': self.param_desc[i]['name'], 'param_value':round(self.param_desc[i]['prior'].transform(p.x[i]),4)})

				fmt = [
				    ('Parameter',       'param_name',   40),
				    ('Estimate',          'param_value',       10)
				]

		# Final printed output
		if printer is True:

			if self.model_type == 'ARIMA':
				self.model_name = "ARIMA(" + str(self.ar) + "," + str(self.integ) + "," + str(self.ma) + ") regression"
				self.cutoff = self.max_lag	
				self.data_length = self.data
			elif self.model_type == 'GAS':
				self.model_name = "GAS(" + str(self.ar) + "," + str(self.integ) + "," + str(self.sc) + ") regression"
				self.cutoff = self.max_lag	
				self.data_length = self.data				
			elif self.model_type == 'VAR':
				self.model_name = "VAR(" + str(self.lags) + ") regression"
				self.cutoff = self.lags			
				self.data_length = self.data[0]
			elif self.model_type in ['EGARCH', 'GARCH']:
				self.model_name = self.model_type + "(" + str(self.p) + "," + str(self.q) + ") regression"
				self.cutoff = self.max_lag		
				self.data_length = self.data	
			elif self.model_type == 'GPNARX':
				self.model_name = "GP-NARX(" + str(self.max_lag) + ") regression"
				self.cutoff = self.max_lag			
				self.data_length = self.data						

			print self.model_name 
			print "=================="
			if obj_type == self.likelihood:
				print "Method: MLE"
			elif obj_type == self.posterior:
				print "Method: MAP"
			print "Number of observations: " + str(len(self.data_length)-self.cutoff)
			print "Log Likelihood: " + str(round(-self.likelihood(p.x),4))
			if obj_type == self.posterior:
				print "Unnormalized Log Posterior: " + str(round(-self.posterior(p.x),4))
			print "AIC: " + str(round(2*len(p.x)+2*self.likelihood(p.x),4))
			print "BIC: " + str(round(2*self.likelihood(p.x) + len(p.x)*log(len(self.data_length)-self.cutoff),4))
			print ""
			print( op.TablePrinter(fmt, ul='=')(data) )
Performs optimization of an objective function
dataset/ETHPy150Open RJT1990/pyflux/pyflux/tsm.py/TSM.optimize_fit